diff --git a/docs/compiled/artplayer-plugin-jassub.js b/docs/compiled/artplayer-plugin-jassub.js index a8c1975b5..c0da6b295 100644 --- a/docs/compiled/artplayer-plugin-jassub.js +++ b/docs/compiled/artplayer-plugin-jassub.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=(t,s,i)=>((t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i)(t,"symbol"!==typeof s?s+"":s,i);typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const s={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},i={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},a=class e extends EventTarget{constructor(t){let s;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),s=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(t.onDemandRender??!0),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(t.offscreenRender??!0),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),s.then(()=>{this._destroyed||(this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:t.wasmUrl??"jassub-worker.wasm",legacyWasmUrl:t.legacyWasmUrl??"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(t.asyncRender??!0),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(t.useLocalFonts??!0),hasBitmapBug:e._hasBitmapBug}),!0===this._offscreenRender&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl]))}).catch(e=>{this._destroyed||this.destroy(e)})}catch(i){s?.catch(()=>{});try{this.destroy()}catch{}throw i}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch{e._supportsSIMD=!1}}static async _testImageBugs(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(await createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()}static async _test(){e._testSIMD(),await e._testImageBugs()}resize(e=0,t=0,s=0,i=0,a=this._video?.paused){if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||this._video?.videoWidth||e,videoHeight:this._videoHeight||this._video?.videoHeight||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=t?.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{navigator?.permissions?.query?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let i;this._colorCallback=null;try{i=new VideoFrame(e),this._videoColorSpace=s[i.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(a){console.warn(a)}finally{i?.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(this._init(),this.dispatchEvent(new CustomEvent("ready")))}async sendMessage(e,t={},s){this._destroyed||(await this._loaded,this._destroyed||(s?this._worker.postMessage({target:e,transferable:s,...t},[...s]):this._worker.postMessage({target:e,...t})))}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){if(this._destroyed)for(const t of e.images||[])t.image?.close?.();else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){this._videoGeneration=(this._videoGeneration||0)+1;for(const e of[this._frameCallback,this._colorCallback])null!=e&&this._video?.cancelVideoFrameCallback?.(e);this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let t,s=!1;const i=e=>{try{e()}catch(i){s||(t=i,s=!0)}};e&&i(()=>{e=this._error(e)}),i(()=>this._removeListeners()),i(()=>this._ro?.disconnect()),i(()=>this._canvasParent?.remove()),this._init?.();const a=[];for(const r of[...this._requests||[]])i(()=>{const e=r();e&&a.push(e)});for(const r of a)i(r);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,i(()=>this._worker.terminate())),s)throw t;return e}};t(a,"_supportsSIMD",null),t(a,"_hasAlphaBug",null),t(a,"_hasBitmapBug",null);let r=a;return function(e){return t=>function(e,t){const s=new r({video:e.video,...t});let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch{}try{a()}catch{}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); +!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=(t,s,i)=>((t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i)(t,"symbol"!==typeof s?s+"":s,i);typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const s={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},i={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},a=class e extends EventTarget{constructor(t){let s;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),s=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(t.onDemandRender??!0),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(t.offscreenRender??!0),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),s.then(()=>{this._destroyed||this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:t.wasmUrl??"jassub-worker.wasm",legacyWasmUrl:t.legacyWasmUrl??"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(t.asyncRender??!0),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(t.useLocalFonts??!0),hasBitmapBug:e._hasBitmapBug})}).catch(e=>{this._destroyed||this.destroy(e)})}catch(i){s?.catch(()=>{});try{this.destroy()}catch{}throw i}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch{e._supportsSIMD=!1}}static async _testImageBugs(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(await createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()}static async _test(){e._testSIMD(),await e._testImageBugs()}resize(e=0,t=0,s=0,i=0,a=this._video?.paused){if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||this._video?.videoWidth||e,videoHeight:this._videoHeight||this._video?.videoHeight||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=t?.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{navigator?.permissions?.query?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let i;this._colorCallback=null;try{i=new VideoFrame(e),this._videoColorSpace=s[i.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(a){console.warn(a)}finally{i?.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(!0!==this._offscreenRender||this._initialOffscreenSent||(this._initialOffscreenSent=!0,this._worker.postMessage({target:"offscreenCanvas",transferable:[this._canvasctrl]},[this._canvasctrl])),this._init(),this.dispatchEvent(new CustomEvent("ready")))}async sendMessage(e,t={},s){this._destroyed||(await this._loaded,this._destroyed||(s?this._worker.postMessage({target:e,transferable:s,...t},[...s]):this._worker.postMessage({target:e,...t})))}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){if(this._destroyed)for(const t of e.images||[])t.image?.close?.();else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){this._videoGeneration=(this._videoGeneration||0)+1;for(const e of[this._frameCallback,this._colorCallback])null!=e&&this._video?.cancelVideoFrameCallback?.(e);this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let t,s=!1;const i=e=>{try{e()}catch(i){s||(t=i,s=!0)}};e&&i(()=>{e=this._error(e)}),i(()=>this._removeListeners()),i(()=>this._ro?.disconnect()),i(()=>this._canvasParent?.remove()),this._init?.();const a=[];for(const r of[...this._requests||[]])i(()=>{const e=r();e&&a.push(e)});for(const r of a)i(r);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,i(()=>this._worker.terminate())),s)throw t;return e}};t(a,"_supportsSIMD",null),t(a,"_hasAlphaBug",null),t(a,"_hasBitmapBug",null);let r=a;return function(e){return t=>function(e,t){const s=new r({video:e.video,...t});let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch{}try{a()}catch{}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); diff --git a/docs/compiled/artplayer-plugin-jassub.legacy.js b/docs/compiled/artplayer-plugin-jassub.legacy.js index b5145e496..892419195 100644 --- a/docs/compiled/artplayer-plugin-jassub.legacy.js +++ b/docs/compiled/artplayer-plugin-jassub.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,a=(t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i,r=(e,r)=>{for(var n in r||(r={}))s.call(r,n)&&a(e,n,r[n]);if(t)for(var n of t(r))i.call(r,n)&&a(e,n,r[n]);return e},n=(e,t,s)=>a(e,"symbol"!==typeof t?t+"":t,s),o=(e,t,s)=>new Promise((i,a)=>{var r=e=>{try{o(s.next(e))}catch(t){a(t)}},n=e=>{try{o(s.throw(e))}catch(t){a(t)}},o=e=>e.done?i(e.value):Promise.resolve(e.value).then(r,n);o((s=s.apply(e,t)).next())});typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const h={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},d={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},l=class e extends EventTarget{constructor(t){var s,i;let a;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),a=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(null==(s=t.onDemandRender)||s),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(null==(i=t.offscreenRender)||i),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),a.then(()=>{var s,i,a,r;this._destroyed||(this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:null!=(s=t.wasmUrl)?s:"jassub-worker.wasm",legacyWasmUrl:null!=(i=t.legacyWasmUrl)?i:"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(null==(a=t.asyncRender)||a),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(null==(r=t.useLocalFonts)||r),hasBitmapBug:e._hasBitmapBug}),!0===this._offscreenRender&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl]))}).catch(e=>{this._destroyed||this.destroy(e)})}catch(r){null==a||a.catch(()=>{});try{this.destroy()}catch(n){}throw r}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch(t){e._supportsSIMD=!1}}static _testImageBugs(){return o(this,null,function*(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch(o){console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(yield createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()})}static _test(){return o(this,null,function*(){e._testSIMD(),yield e._testImageBugs()})}resize(e=0,t=0,s=0,i=0,a=(e=>null==(e=this._video)?void 0:e.paused)()){var r,n;if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||(null==(r=this._video)?void 0:r.videoWidth)||e,videoHeight:this._videoHeight||(null==(n=this._video)?void 0:n.videoHeight)||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=null==t?void 0:t.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){var t;try{(null==(t=null==navigator?void 0:navigator.permissions)?void 0:t.query)?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(s){console.warn("Local fonts API:",s)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let s;this._colorCallback=null;try{s=new VideoFrame(e),this._videoColorSpace=h[s.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(i){console.warn(i)}finally{null==s||s.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(this._init(),this.dispatchEvent(new CustomEvent("ready")))}sendMessage(e){return o(this,arguments,function*(e,t={},s){this._destroyed||(yield this._loaded,this._destroyed||(s?this._worker.postMessage(r({target:e,transferable:s},t),[...s]):this._worker.postMessage(r({target:e},t))))})}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){var t,s;if(this._destroyed)for(const i of e.images||[])null==(s=null==(t=i.image)?void 0:t.close)||s.call(t);else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){var e,t;this._videoGeneration=(this._videoGeneration||0)+1;for(const s of[this._frameCallback,this._colorCallback])null!=s&&(null==(t=null==(e=this._video)?void 0:e.cancelVideoFrameCallback)||t.call(e,s));this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){var t;if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let s,i=!1;const a=e=>{try{e()}catch(t){i||(s=t,i=!0)}};e&&a(()=>{e=this._error(e)}),a(()=>this._removeListeners()),a(()=>{var e;return null==(e=this._ro)?void 0:e.disconnect()}),a(()=>{var e;return null==(e=this._canvasParent)?void 0:e.remove()}),null==(t=this._init)||t.call(this);const r=[];for(const n of[...this._requests||[]])a(()=>{const e=n();e&&r.push(e)});for(const n of r)a(n);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,a(()=>this._worker.terminate())),i)throw s;return e}};n(l,"_supportsSIMD",null),n(l,"_hasAlphaBug",null),n(l,"_hasBitmapBug",null);let c=l;return function(e){return t=>function(e,t){const s=new c(r({video:e.video},t));let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch(o){}try{a()}catch(o){}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); +!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,a=(t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i,r=(e,r)=>{for(var n in r||(r={}))s.call(r,n)&&a(e,n,r[n]);if(t)for(var n of t(r))i.call(r,n)&&a(e,n,r[n]);return e},n=(e,t,s)=>a(e,"symbol"!==typeof t?t+"":t,s),o=(e,t,s)=>new Promise((i,a)=>{var r=e=>{try{o(s.next(e))}catch(t){a(t)}},n=e=>{try{o(s.throw(e))}catch(t){a(t)}},o=e=>e.done?i(e.value):Promise.resolve(e.value).then(r,n);o((s=s.apply(e,t)).next())});typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const h={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},d={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},l=class e extends EventTarget{constructor(t){var s,i;let a;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),a=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(null==(s=t.onDemandRender)||s),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(null==(i=t.offscreenRender)||i),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),a.then(()=>{var s,i,a,r;this._destroyed||this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:null!=(s=t.wasmUrl)?s:"jassub-worker.wasm",legacyWasmUrl:null!=(i=t.legacyWasmUrl)?i:"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(null==(a=t.asyncRender)||a),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(null==(r=t.useLocalFonts)||r),hasBitmapBug:e._hasBitmapBug})}).catch(e=>{this._destroyed||this.destroy(e)})}catch(r){null==a||a.catch(()=>{});try{this.destroy()}catch(n){}throw r}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch(t){e._supportsSIMD=!1}}static _testImageBugs(){return o(this,null,function*(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch(o){console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(yield createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()})}static _test(){return o(this,null,function*(){e._testSIMD(),yield e._testImageBugs()})}resize(e=0,t=0,s=0,i=0,a=(e=>null==(e=this._video)?void 0:e.paused)()){var r,n;if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||(null==(r=this._video)?void 0:r.videoWidth)||e,videoHeight:this._videoHeight||(null==(n=this._video)?void 0:n.videoHeight)||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=null==t?void 0:t.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){var t;try{(null==(t=null==navigator?void 0:navigator.permissions)?void 0:t.query)?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(s){console.warn("Local fonts API:",s)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let s;this._colorCallback=null;try{s=new VideoFrame(e),this._videoColorSpace=h[s.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(i){console.warn(i)}finally{null==s||s.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(!0!==this._offscreenRender||this._initialOffscreenSent||(this._initialOffscreenSent=!0,this._worker.postMessage({target:"offscreenCanvas",transferable:[this._canvasctrl]},[this._canvasctrl])),this._init(),this.dispatchEvent(new CustomEvent("ready")))}sendMessage(e){return o(this,arguments,function*(e,t={},s){this._destroyed||(yield this._loaded,this._destroyed||(s?this._worker.postMessage(r({target:e,transferable:s},t),[...s]):this._worker.postMessage(r({target:e},t))))})}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){var t,s;if(this._destroyed)for(const i of e.images||[])null==(s=null==(t=i.image)?void 0:t.close)||s.call(t);else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){var e,t;this._videoGeneration=(this._videoGeneration||0)+1;for(const s of[this._frameCallback,this._colorCallback])null!=s&&(null==(t=null==(e=this._video)?void 0:e.cancelVideoFrameCallback)||t.call(e,s));this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){var t;if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let s,i=!1;const a=e=>{try{e()}catch(t){i||(s=t,i=!0)}};e&&a(()=>{e=this._error(e)}),a(()=>this._removeListeners()),a(()=>{var e;return null==(e=this._ro)?void 0:e.disconnect()}),a(()=>{var e;return null==(e=this._canvasParent)?void 0:e.remove()}),null==(t=this._init)||t.call(this);const r=[];for(const n of[...this._requests||[]])a(()=>{const e=n();e&&r.push(e)});for(const n of r)a(n);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,a(()=>this._worker.terminate())),i)throw s;return e}};n(l,"_supportsSIMD",null),n(l,"_hasAlphaBug",null),n(l,"_hasBitmapBug",null);let c=l;return function(e){return t=>function(e,t){const s=new c(r({video:e.video},t));let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch(o){}try{a()}catch(o){}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); diff --git a/docs/compiled/artplayer-plugin-jassub.mjs b/docs/compiled/artplayer-plugin-jassub.mjs index e7f96d74a..bb1d5a5a2 100644 --- a/docs/compiled/artplayer-plugin-jassub.mjs +++ b/docs/compiled/artplayer-plugin-jassub.mjs @@ -147,7 +147,7 @@ const _o = class _o extends EventTarget { // @ts-ignore useLocalFonts: typeof queryLocalFonts < "u" && (e.useLocalFonts ?? true), hasBitmapBug: _o._hasBitmapBug - }), this._offscreenRender === true && this.sendMessage("offscreenCanvas", null, [this._canvasctrl]); + }); }).catch((error) => { if (!this._destroyed) this.destroy(error); }); @@ -581,6 +581,10 @@ const _o = class _o extends EventTarget { } _ready() { if (this._destroyed) return; + if (this._offscreenRender === true && !this._initialOffscreenSent) { + this._initialOffscreenSent = true; + this._worker.postMessage({ target: "offscreenCanvas", transferable: [this._canvasctrl] }, [this._canvasctrl]); + } this._init(), this.dispatchEvent(new CustomEvent("ready")); } /** diff --git a/package.json b/package.json index 19840d3ad..3a4eff9c4 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: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/multiple-subtitles-merge.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-frames.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.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-merge.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-frames.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.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:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs", "test": "yarn test:node && yarn test:baseline", "test:browser": "playwright test", @@ -90,7 +90,7 @@ "test:vtt-thumbnail-types-package": "node refactor/scripts/vtt-thumbnail-package-types.mjs", "test:multiple-subtitles": "node --test test/multiple-subtitles-merge.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 refactor/scripts/multiple-subtitles-contract.test.mjs refactor/scripts/multiple-subtitles-runtime-types.test.mjs refactor/scripts/multiple-subtitles-types.test.mjs", "test:multiple-subtitles-types-package": "node refactor/scripts/multiple-subtitles-package-types.mjs", - "test:jassub": "node --test 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 refactor/scripts/jassub-contract.test.mjs refactor/scripts/jassub-provenance.test.mjs refactor/scripts/jassub-failures.test.mjs refactor/scripts/jassub-types.test.mjs refactor/scripts/jassub-vendor-patch.test.mjs", + "test:jassub": "node --test 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 refactor/scripts/jassub-contract.test.mjs refactor/scripts/jassub-provenance.test.mjs refactor/scripts/jassub-failures.test.mjs refactor/scripts/jassub-types.test.mjs refactor/scripts/jassub-vendor-patch.test.mjs", "test:jassub-types": "node --test refactor/scripts/jassub-types.test.mjs", "test:jassub-types-package": "node refactor/scripts/jassub-package-types.mjs", "check:ci": "node refactor/scripts/ci-workflow.mjs", diff --git a/packages/artplayer-plugin-jassub/ARCHITECTURE.md b/packages/artplayer-plugin-jassub/ARCHITECTURE.md index a763edfeb..4c56492aa 100644 --- a/packages/artplayer-plugin-jassub/ARCHITECTURE.md +++ b/packages/artplayer-plugin-jassub/ARCHITECTURE.md @@ -72,7 +72,15 @@ The original wrapper matched upstream jassub 1.8.8 apart from formatting and the PKG-JASSUB-07 records its local lifecycle/clock patch separately in `../../refactor/baselines/jassub-vendor-patch.json` and the accompanying patch file. Keep original and patched fingerprints distinct; do not call the changed wrapper an -unmodified upstream file. The +unmodified upstream file. PKG-JASSUB-08 adds a separate follow-up patch in +`../../refactor/baselines/jassub-offscreen-patch.json`: initial offscreen ownership +is transferred synchronously when the Worker reports ready, before resolving the +loaded gate and dispatching the public ready event. Otherwise a queued resize can +ask the Worker to return main-thread images while the instance has no main-thread +context. Duplicate ready delivery must not transfer the same canvas twice. The +explicit main-thread/custom-canvas and unsupported-capability paths keep their +existing selection. Later hybrid detach/reattach remains separate and must retain +its own rendering/lifetime checks. The worker JS and default font match that archive byte-for-byte. Local WASM instead matches the exact Pages nightly blobs associated with source 6b19a04ddfbad8f9bfd3237395788dd76218841b. Its build workflow and seven submodule revisions are pinned in the separate @@ -123,6 +131,11 @@ The candidate's default onDemandRender path is tested through playback/seek/layo Chromium/Firefox/WebKit. jassub-lifecycle.spec.js additionally checks actual replacement video pixels, numerical fallback playbackRate, repeated teardown, invalid-URL constructor rollback and a genuine asynchronous CSP Worker error reaching a pending query. These -are distinct from default offscreen mode, full devices and sustained memory/GPU release, -which remain unverified. See +are distinct from full devices and sustained memory/GPU release, which remain +unverified. Set ARTPLAYER_JASSUB_OFFSCREEN=default to omit the option and exercise +the browser's actual default selection. The test copies the displayed canvas bitmap +to a separate readback canvas, so it supports both transferred and main-thread +canvases. PKG-JASSUB-08 records default-mode Chromium/Firefox rendering and WebKit's +capability fallback separately; this does not prove physical Safari/mobile behavior. +See `../../refactor/baselines/jassub-contract.md` for precise contract and provenance evidence. diff --git a/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js b/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js index a8c1975b5..c0da6b295 100644 --- a/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js +++ b/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=(t,s,i)=>((t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i)(t,"symbol"!==typeof s?s+"":s,i);typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const s={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},i={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},a=class e extends EventTarget{constructor(t){let s;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),s=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(t.onDemandRender??!0),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(t.offscreenRender??!0),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),s.then(()=>{this._destroyed||(this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:t.wasmUrl??"jassub-worker.wasm",legacyWasmUrl:t.legacyWasmUrl??"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(t.asyncRender??!0),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(t.useLocalFonts??!0),hasBitmapBug:e._hasBitmapBug}),!0===this._offscreenRender&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl]))}).catch(e=>{this._destroyed||this.destroy(e)})}catch(i){s?.catch(()=>{});try{this.destroy()}catch{}throw i}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch{e._supportsSIMD=!1}}static async _testImageBugs(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(await createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()}static async _test(){e._testSIMD(),await e._testImageBugs()}resize(e=0,t=0,s=0,i=0,a=this._video?.paused){if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||this._video?.videoWidth||e,videoHeight:this._videoHeight||this._video?.videoHeight||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=t?.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{navigator?.permissions?.query?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let i;this._colorCallback=null;try{i=new VideoFrame(e),this._videoColorSpace=s[i.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(a){console.warn(a)}finally{i?.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(this._init(),this.dispatchEvent(new CustomEvent("ready")))}async sendMessage(e,t={},s){this._destroyed||(await this._loaded,this._destroyed||(s?this._worker.postMessage({target:e,transferable:s,...t},[...s]):this._worker.postMessage({target:e,...t})))}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){if(this._destroyed)for(const t of e.images||[])t.image?.close?.();else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){this._videoGeneration=(this._videoGeneration||0)+1;for(const e of[this._frameCallback,this._colorCallback])null!=e&&this._video?.cancelVideoFrameCallback?.(e);this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let t,s=!1;const i=e=>{try{e()}catch(i){s||(t=i,s=!0)}};e&&i(()=>{e=this._error(e)}),i(()=>this._removeListeners()),i(()=>this._ro?.disconnect()),i(()=>this._canvasParent?.remove()),this._init?.();const a=[];for(const r of[...this._requests||[]])i(()=>{const e=r();e&&a.push(e)});for(const r of a)i(r);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,i(()=>this._worker.terminate())),s)throw t;return e}};t(a,"_supportsSIMD",null),t(a,"_hasAlphaBug",null),t(a,"_hasBitmapBug",null);let r=a;return function(e){return t=>function(e,t){const s=new r({video:e.video,...t});let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch{}try{a()}catch{}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); +!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=(t,s,i)=>((t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i)(t,"symbol"!==typeof s?s+"":s,i);typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const s={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},i={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},a=class e extends EventTarget{constructor(t){let s;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),s=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(t.onDemandRender??!0),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(t.offscreenRender??!0),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),s.then(()=>{this._destroyed||this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:t.wasmUrl??"jassub-worker.wasm",legacyWasmUrl:t.legacyWasmUrl??"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(t.asyncRender??!0),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(t.useLocalFonts??!0),hasBitmapBug:e._hasBitmapBug})}).catch(e=>{this._destroyed||this.destroy(e)})}catch(i){s?.catch(()=>{});try{this.destroy()}catch{}throw i}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch{e._supportsSIMD=!1}}static async _testImageBugs(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(await createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()}static async _test(){e._testSIMD(),await e._testImageBugs()}resize(e=0,t=0,s=0,i=0,a=this._video?.paused){if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||this._video?.videoWidth||e,videoHeight:this._videoHeight||this._video?.videoHeight||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=t?.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{navigator?.permissions?.query?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let i;this._colorCallback=null;try{i=new VideoFrame(e),this._videoColorSpace=s[i.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(a){console.warn(a)}finally{i?.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(!0!==this._offscreenRender||this._initialOffscreenSent||(this._initialOffscreenSent=!0,this._worker.postMessage({target:"offscreenCanvas",transferable:[this._canvasctrl]},[this._canvasctrl])),this._init(),this.dispatchEvent(new CustomEvent("ready")))}async sendMessage(e,t={},s){this._destroyed||(await this._loaded,this._destroyed||(s?this._worker.postMessage({target:e,transferable:s,...t},[...s]):this._worker.postMessage({target:e,...t})))}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){if(this._destroyed)for(const t of e.images||[])t.image?.close?.();else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){this._videoGeneration=(this._videoGeneration||0)+1;for(const e of[this._frameCallback,this._colorCallback])null!=e&&this._video?.cancelVideoFrameCallback?.(e);this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let t,s=!1;const i=e=>{try{e()}catch(i){s||(t=i,s=!0)}};e&&i(()=>{e=this._error(e)}),i(()=>this._removeListeners()),i(()=>this._ro?.disconnect()),i(()=>this._canvasParent?.remove()),this._init?.();const a=[];for(const r of[...this._requests||[]])i(()=>{const e=r();e&&a.push(e)});for(const r of a)i(r);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,i(()=>this._worker.terminate())),s)throw t;return e}};t(a,"_supportsSIMD",null),t(a,"_hasAlphaBug",null),t(a,"_hasBitmapBug",null);let r=a;return function(e){return t=>function(e,t){const s=new r({video:e.video,...t});let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch{}try{a()}catch{}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); diff --git a/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js b/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js index b5145e496..892419195 100644 --- a/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js +++ b/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,a=(t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i,r=(e,r)=>{for(var n in r||(r={}))s.call(r,n)&&a(e,n,r[n]);if(t)for(var n of t(r))i.call(r,n)&&a(e,n,r[n]);return e},n=(e,t,s)=>a(e,"symbol"!==typeof t?t+"":t,s),o=(e,t,s)=>new Promise((i,a)=>{var r=e=>{try{o(s.next(e))}catch(t){a(t)}},n=e=>{try{o(s.throw(e))}catch(t){a(t)}},o=e=>e.done?i(e.value):Promise.resolve(e.value).then(r,n);o((s=s.apply(e,t)).next())});typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const h={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},d={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},l=class e extends EventTarget{constructor(t){var s,i;let a;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),a=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(null==(s=t.onDemandRender)||s),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(null==(i=t.offscreenRender)||i),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),a.then(()=>{var s,i,a,r;this._destroyed||(this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:null!=(s=t.wasmUrl)?s:"jassub-worker.wasm",legacyWasmUrl:null!=(i=t.legacyWasmUrl)?i:"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(null==(a=t.asyncRender)||a),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(null==(r=t.useLocalFonts)||r),hasBitmapBug:e._hasBitmapBug}),!0===this._offscreenRender&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl]))}).catch(e=>{this._destroyed||this.destroy(e)})}catch(r){null==a||a.catch(()=>{});try{this.destroy()}catch(n){}throw r}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch(t){e._supportsSIMD=!1}}static _testImageBugs(){return o(this,null,function*(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch(o){console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(yield createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()})}static _test(){return o(this,null,function*(){e._testSIMD(),yield e._testImageBugs()})}resize(e=0,t=0,s=0,i=0,a=(e=>null==(e=this._video)?void 0:e.paused)()){var r,n;if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||(null==(r=this._video)?void 0:r.videoWidth)||e,videoHeight:this._videoHeight||(null==(n=this._video)?void 0:n.videoHeight)||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=null==t?void 0:t.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){var t;try{(null==(t=null==navigator?void 0:navigator.permissions)?void 0:t.query)?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(s){console.warn("Local fonts API:",s)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let s;this._colorCallback=null;try{s=new VideoFrame(e),this._videoColorSpace=h[s.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(i){console.warn(i)}finally{null==s||s.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(this._init(),this.dispatchEvent(new CustomEvent("ready")))}sendMessage(e){return o(this,arguments,function*(e,t={},s){this._destroyed||(yield this._loaded,this._destroyed||(s?this._worker.postMessage(r({target:e,transferable:s},t),[...s]):this._worker.postMessage(r({target:e},t))))})}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){var t,s;if(this._destroyed)for(const i of e.images||[])null==(s=null==(t=i.image)?void 0:t.close)||s.call(t);else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){var e,t;this._videoGeneration=(this._videoGeneration||0)+1;for(const s of[this._frameCallback,this._colorCallback])null!=s&&(null==(t=null==(e=this._video)?void 0:e.cancelVideoFrameCallback)||t.call(e,s));this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){var t;if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let s,i=!1;const a=e=>{try{e()}catch(t){i||(s=t,i=!0)}};e&&a(()=>{e=this._error(e)}),a(()=>this._removeListeners()),a(()=>{var e;return null==(e=this._ro)?void 0:e.disconnect()}),a(()=>{var e;return null==(e=this._canvasParent)?void 0:e.remove()}),null==(t=this._init)||t.call(this);const r=[];for(const n of[...this._requests||[]])a(()=>{const e=n();e&&r.push(e)});for(const n of r)a(n);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,a(()=>this._worker.terminate())),i)throw s;return e}};n(l,"_supportsSIMD",null),n(l,"_hasAlphaBug",null),n(l,"_hasBitmapBug",null);let c=l;return function(e){return t=>function(e,t){const s=new c(r({video:e.video},t));let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch(o){}try{a()}catch(o){}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); +!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginJassub=t(),define(function(){return e.artplayerPluginJassub})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginJassub=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,a=(t,s,i)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[s]=i,r=(e,r)=>{for(var n in r||(r={}))s.call(r,n)&&a(e,n,r[n]);if(t)for(var n of t(r))i.call(r,n)&&a(e,n,r[n]);return e},n=(e,t,s)=>a(e,"symbol"!==typeof t?t+"":t,s),o=(e,t,s)=>new Promise((i,a)=>{var r=e=>{try{o(s.next(e))}catch(t){a(t)}},n=e=>{try{o(s.throw(e))}catch(t){a(t)}},o=e=>e.done?i(e.value):Promise.resolve(e.value).then(r,n);o((s=s.apply(e,t)).next())});typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype.requestVideoFrameCallback=function(e){Object.prototype.hasOwnProperty.call(this,"_rvfcpolyfillmap")||(this._rvfcpolyfillmap={});const t=this._rvfcpolyfillid=(this._rvfcpolyfillid||0)+1,s=performance.now(),i=this.getVideoPlaybackQuality(),a=this.currentTime,r=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames,n=(o,h)=>{if(!(t in this._rvfcpolyfillmap))return;const d=this.getVideoPlaybackQuality(),l=this.mozPresentedFrames||this.mozPaintedFrames||d.totalVideoFrames-d.droppedVideoFrames,c=l>r,_=0===r&&0===l&&0===i.totalVideoFrames&&0===i.droppedVideoFrames&&0===d.totalVideoFrames&&0===d.droppedVideoFrames&&Number.isFinite(this.currentTime)&&this.currentTime!==a&&this.readyState>=2&&!this.seeking&&h-s>=1e3/30;if(c||_){const s=this.mozFrameDelay||d.totalFrameDelay-i.totalFrameDelay||0,a=h-o;delete this._rvfcpolyfillmap[t],e(h,{presentationTime:h+1e3*s,expectedDisplayTime:h+a,width:this.videoWidth,height:this.videoHeight,mediaTime:_&&!c?Math.max(0,this.currentTime):Math.max(0,this.currentTime||0)+a/1e3,presentedFrames:l,processingDuration:s})}else this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(h,e))};return this._rvfcpolyfillmap[t]=requestAnimationFrame(e=>n(s,e)),t},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(e){const t=this._rvfcpolyfillmap;t&&e in t&&(cancelAnimationFrame(t[e]),delete t[e])});const h={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},d={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},l=class e extends EventTarget{constructor(t){var s,i;let a;super(),this._requests=new Set;try{if(!globalThis.Worker)throw this.destroy("Worker not supported");if(!t)throw this.destroy("No options provided");if(this._loaded=new Promise(e=>{this._init=e}),a=e._test(),this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(null==(s=t.onDemandRender)||s),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!t.canvas&&(null==(i=t.offscreenRender)||i),this.timeOffset=t.timeOffset||0,this._video=t.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=t.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!t.debug,this.prescaleFactor=t.prescaleFactor||1,this.prescaleHeightLimit=t.prescaleHeightLimit||1080,this.maxRenderHeight=t.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>{this._destroyed||this.setRate(this._video.playbackRate)},this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(t.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(t.workerUrl||"jassub-worker.js"),this._worker.onmessage=e=>this._onmessage(e),this._worker.onerror=e=>this._error(e),a.then(()=>{var s,i,a,r;this._destroyed||this._worker.postMessage({target:"init",wasmUrl:e._supportsSIMD&&t.modernWasmUrl?t.modernWasmUrl:null!=(s=t.wasmUrl)?s:"jassub-worker.wasm",legacyWasmUrl:null!=(i=t.legacyWasmUrl)?i:"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(null==(a=t.asyncRender)||a),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:t.blendMode||"js",subUrl:t.subUrl,subContent:t.subContent||null,fonts:t.fonts||[],availableFonts:t.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:t.fallbackFont||"liberation sans",debug:this.debug,targetFps:t.targetFps||24,dropAllAnimations:t.dropAllAnimations,dropAllBlur:t.dropAllBlur,libassMemoryLimit:t.libassMemoryLimit||0,libassGlyphLimit:t.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(null==(r=t.useLocalFonts)||r),hasBitmapBug:e._hasBitmapBug})}).catch(e=>{this._destroyed||this.destroy(e)})}catch(r){null==a||a.catch(()=>{});try{this.destroy()}catch(n){}throw r}}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _testSIMD(){if(null===e._supportsSIMD)try{e._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch(t){e._supportsSIMD=!1}}static _testImageBugs(){return o(this,null,function*(){if(null!==e._hasBitmapBug)return;const t=document.createElement("canvas"),s=t.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas rendering not supported");if("function"==typeof ImageData.prototype.constructor)try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch(o){console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(e,t,i){const a=s.createImageData(t,i);return e&&a.data.set(e),a}}const i=document.createElement("canvas"),a=i.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("Canvas rendering not supported");t.width=i.width=1,t.height=i.height=1,s.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const r=a.getImageData(0,0,1,1).data;s.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(t,0,0);const n=a.getImageData(0,0,1,1).data;if(e._hasAlphaBug=r[1]!==n[1],e._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const t=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);a.drawImage(yield createImageBitmap(new ImageData(t,1)),0,0);const{data:s}=a.getImageData(0,0,1,1);e._hasBitmapBug=!1;for(const[i,a]of s.entries())if(Math.abs(t[i]-a)>15){e._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else e._hasBitmapBug=!1;t.remove(),i.remove()})}static _test(){return o(this,null,function*(){e._testSIMD(),yield e._testImageBugs()})}resize(e=0,t=0,s=0,i=0,a=(e=>null==(e=this._video)?void 0:e.paused)()){var r,n;if(!this._destroyed){if((!e||!t)&&this._video){const a=this._getVideoPosition();let r=null;if(this._videoWidth){const e=this._video.videoWidth/this._videoWidth,t=this._video.videoHeight/this._videoHeight;r=this._computeCanvasSize((a.width||0)/e,(a.height||0)/t)}else r=this._computeCanvasSize(a.width||0,a.height||0);e=r.width,t=r.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",a&&!1===this.busy?this.busy=!0:a=!1,this.sendMessage("canvas",{width:e,height:t,videoWidth:this._videoWidth||(null==(r=this._video)?void 0:r.videoWidth)||e,videoHeight:this._videoHeight||(null==(n=this._video)?void 0:n.videoHeight)||t,force:a})}}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:a}=this._video;e=i,t=a,i/a>s?e=Math.floor(a*s):t=Math.floor(i/s);return{width:e,height:t,x:(i-e)/2,y:(a-t)/2}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const a=s<1?-1:1;let r=t*i;a*r*s<=a*this.prescaleHeightLimit?r*=s:a*r0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){if(this._destroyed)return;const t={seeking:!0,waiting:!0,playing:!1}[e];null!=t&&(this._playstate=t),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){if(!this._destroyed)if(e instanceof HTMLVideoElement){if(this._removeListeners(),this._video=e,this._videoWidth=this._videoHeight=0,this._videoColorSpace=null,this._canvasParent&&this._canvasParent.parentNode!==e.parentNode&&e.insertAdjacentElement("afterend",this._canvasParent),this._onDemandRender)this._requestFrame();else{this._playstate=e.paused;for(const t of["timeupdate","progress","waiting","seeking","playing"])e.addEventListener(t,this._boundTimeUpdate,!1);e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)}"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))}else this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s}={})=>{e(t,s)})}styleOverride(e){this.sendMessage("styleOverride",{style:e})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s}={})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}setDefaultFont(e){this.sendMessage("defaultFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=null==t?void 0:t.find(t=>t.fullName.toLowerCase()===e);s&&s.blob().then(e=>{e.arrayBuffer().then(e=>{this.addFont(new Uint8Array(e))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){var t;try{(null==(t=null==navigator?void 0:navigator.permissions)?void 0:t.query)?navigator.permissions.query({name:"local-fonts"}).then(t=>{"granted"===t.state&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(s){console.warn("Local fonts API:",s)}}_unbusy(){this._destroyed||(this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1)}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._requestFrame()}_requestFrame(){if(this._destroyed||!this._video||null!=this._frameCallback)return;const e=this._video,t=this._videoGeneration;this._frameCallback=e.requestVideoFrameCallback((s,i)=>{this._destroyed||t!==this._videoGeneration||e!==this._video||(this._frameCallback=null,this._handleRVFC(s,i))})}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){if(this._destroyed||null!=this._colorCallback)return;const e=this._video,t=this._videoGeneration;this._colorCallback=e.requestVideoFrameCallback(()=>{if(this._destroyed||t!==this._videoGeneration||e!==this._video)return;let s;this._colorCallback=null;try{s=new VideoFrame(e),this._videoColorSpace=h[s.colorSpace.matrix],this.sendMessage("getColorSpace")}catch(i){console.warn(i)}finally{null==s||s.close()}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:a,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==a)&&(this._canvasctrl.width=i,this._canvasctrl.height=a,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const n of e)n.image&&(t?(this._ctx.drawImage(n.image,n.x,n.y),n.image.close()):(this._bufferCanvas.width=n.w,this._bufferCanvas.height=n.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(n.image)),n.w,n.h),0,0),this._ctx.drawImage(this._bufferCanvas,n.x,n.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let t=0;const i=s.bitmaps||e.length;delete s.bitmaps;for(const e in s)t+=s[e];console.log("Bitmaps: "+i+" Total: "+(0|t)+"ms",s)}}_fixAlpha(t){if(e._hasAlphaBug)for(let e=3;e1?t[e]:1;return t}_ready(){this._destroyed||(!0!==this._offscreenRender||this._initialOffscreenSent||(this._initialOffscreenSent=!0,this._worker.postMessage({target:"offscreenCanvas",transferable:[this._canvasctrl]},[this._canvasctrl])),this._init(),this.dispatchEvent(new CustomEvent("ready")))}sendMessage(e){return o(this,arguments,function*(e,t={},s){this._destroyed||(yield this._loaded,this._destroyed||(s?this._worker.postMessage(r({target:e,transferable:s},t),[...s]):this._worker.postMessage(r({target:e},t))))})}_fetchFromWorker(e,t){if(this._destroyed)return void t(new Error("JASSUB instance destroyed"));const s=this._worker;let i,a=!1;const r=()=>{s.removeEventListener("message",o),s.removeEventListener("error",h),clearTimeout(i),this._requests.delete(d)},n=(e,s)=>{a||(a=!0,r(),t(e,s))},o=({data:t})=>{t.target===e.target&&n(null,t)},h=e=>n(e),d=()=>{if(!a)return a=!0,r(),()=>t(new Error("JASSUB instance destroyed"))};try{this._requests.add(d),s.addEventListener("message",o),s.addEventListener("error",h),i=setTimeout(()=>h(new Error("Error: Timeout while try to fetch "+e.target)),5e3),s.postMessage(e)}catch(l){if(a)throw l;n(l)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){var t,s;if(this._destroyed)for(const i of e.images||[])null==(s=null==(t=i.image)?void 0:t.close)||s.call(t);else this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){var e,t;this._videoGeneration=(this._videoGeneration||0)+1;for(const s of[this._frameCallback,this._colorCallback])null!=s&&(null==(t=null==(e=this._video)?void 0:e.cancelVideoFrameCallback)||t.call(e,s));this._frameCallback=this._colorCallback=null,this._lastDemandTime=null,this._onDemandRender&&(this.busy=!1),this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){var t;if(this._destroyed)return e&&this._error(e);this._destroyed=!0;let s,i=!1;const a=e=>{try{e()}catch(t){i||(s=t,i=!0)}};e&&a(()=>{e=this._error(e)}),a(()=>this._removeListeners()),a(()=>{var e;return null==(e=this._ro)?void 0:e.disconnect()}),a(()=>{var e;return null==(e=this._canvasParent)?void 0:e.remove()}),null==(t=this._init)||t.call(this);const r=[];for(const n of[...this._requests||[]])a(()=>{const e=n();e&&r.push(e)});for(const n of r)a(n);if(this._worker&&(this._worker.onmessage=this._worker.onerror=null,a(()=>this._worker.terminate())),i)throw s;return e}};n(l,"_supportsSIMD",null),n(l,"_hasAlphaBug",null),n(l,"_hasBitmapBug",null);let c=l;return function(e){return t=>function(e,t){const s=new c(r({video:e.video},t));let i=!1;const a=()=>{if(!i&&!s._destroyed){i=!0;try{s.destroy()}catch(e){throw i=!1,e}}};try{s._canvasParent&&(s._canvasParent.style.zIndex=20),e.on("destroy",a)}catch(n){try{e.off("destroy",a)}catch(o){}try{a()}catch(o){}throw n}return{name:"artplayerPluginJassub",instance:s}}(t,e)}}); diff --git a/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.mjs b/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.mjs index e7f96d74a..bb1d5a5a2 100644 --- a/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.mjs +++ b/packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.mjs @@ -147,7 +147,7 @@ const _o = class _o extends EventTarget { // @ts-ignore useLocalFonts: typeof queryLocalFonts < "u" && (e.useLocalFonts ?? true), hasBitmapBug: _o._hasBitmapBug - }), this._offscreenRender === true && this.sendMessage("offscreenCanvas", null, [this._canvasctrl]); + }); }).catch((error) => { if (!this._destroyed) this.destroy(error); }); @@ -581,6 +581,10 @@ const _o = class _o extends EventTarget { } _ready() { if (this._destroyed) return; + if (this._offscreenRender === true && !this._initialOffscreenSent) { + this._initialOffscreenSent = true; + this._worker.postMessage({ target: "offscreenCanvas", transferable: [this._canvasctrl] }, [this._canvasctrl]); + } this._init(), this.dispatchEvent(new CustomEvent("ready")); } /** diff --git a/packages/artplayer-plugin-jassub/src/jassub.es.js b/packages/artplayer-plugin-jassub/src/jassub.es.js index 904b40888..6bd2bc2c6 100644 --- a/packages/artplayer-plugin-jassub/src/jassub.es.js +++ b/packages/artplayer-plugin-jassub/src/jassub.es.js @@ -143,7 +143,7 @@ class o extends EventTarget { // @ts-ignore useLocalFonts: typeof queryLocalFonts < "u" && (e.useLocalFonts ?? !0), hasBitmapBug: o._hasBitmapBug - }), this._offscreenRender === !0 && this.sendMessage("offscreenCanvas", null, [this._canvasctrl]); + }); }).catch((error) => { if (!this._destroyed) this.destroy(error); }); @@ -580,6 +580,10 @@ class o extends EventTarget { } _ready() { if (this._destroyed) return; + if (this._offscreenRender === !0 && !this._initialOffscreenSent) { + this._initialOffscreenSent = true; + this._worker.postMessage({ target: "offscreenCanvas", transferable: [this._canvasctrl] }, [this._canvasctrl]); + } this._init(), this.dispatchEvent(new CustomEvent("ready")); } /** diff --git a/refactor/baselines/jassub-offscreen-patch.json b/refactor/baselines/jassub-offscreen-patch.json new file mode 100644 index 000000000..b52ff04e5 --- /dev/null +++ b/refactor/baselines/jassub-offscreen-patch.json @@ -0,0 +1,11 @@ +{ + "task": "PKG-JASSUB-08", + "baselineCommit": "0f3c068aae1415c2d40ede8708f02f4c5864fe7a", + "file": "packages/artplayer-plugin-jassub/src/jassub.es.js", + "originalSha256LF": "1fdcf24d206e8711348dddcb5fe7b656007a9b1d81a992bb497c6d10bd0a2cdb", + "patchedSha256LF": "6a96af7914f702eb7d6303b466cbe16abddd278040f60cd29f153cdf60e92cb2", + "patchFile": "refactor/baselines/jassub-offscreen.patch", + "patchSha256LF": "b6cb5c4cb3c9fab920724fa7ddfe7a6b58db68d177f720231f5823fc5bfd6dac", + "predecessor": "refactor/baselines/jassub-vendor-patch.json", + "purpose": "Transfer the initial offscreen canvas on Worker readiness before releasing queued resize/render messages; keep later reattachment behavior unchanged." +} diff --git a/refactor/baselines/jassub-offscreen-validation.json b/refactor/baselines/jassub-offscreen-validation.json new file mode 100644 index 000000000..b4febe42e --- /dev/null +++ b/refactor/baselines/jassub-offscreen-validation.json @@ -0,0 +1,9356 @@ +{ + "task": "PKG-JASSUB-08", + "recordedAt": "2026-09-13T18:27:03.863Z", + "node": "v24.21.0", + "platform": "win32", + "patch": { + "task": "PKG-JASSUB-08", + "baselineCommit": "0f3c068aae1415c2d40ede8708f02f4c5864fe7a", + "file": "packages/artplayer-plugin-jassub/src/jassub.es.js", + "originalSha256LF": "1fdcf24d206e8711348dddcb5fe7b656007a9b1d81a992bb497c6d10bd0a2cdb", + "patchedSha256LF": "6a96af7914f702eb7d6303b466cbe16abddd278040f60cd29f153cdf60e92cb2", + "patchFile": "refactor/baselines/jassub-offscreen.patch", + "patchSha256LF": "b6cb5c4cb3c9fab920724fa7ddfe7a6b58db68d177f720231f5823fc5bfd6dac", + "predecessor": "refactor/baselines/jassub-vendor-patch.json", + "purpose": "Transfer the initial offscreen canvas on Worker readiness before releasing queued resize/render messages; keep later reattachment behavior unchanged." + }, + "files": [ + { + "file": "test/jassub-offscreen.test.js", + "sha256": "0de49e8b26ad8f4b109649c00caa54f708457f3c6e86154ba24078b7927a62f9" + }, + { + "file": "test/browser/jassub-native.spec.js", + "sha256": "818ae5af6ee64daf2f5d8ccf0b5a42c03b1b7eb878b2b76c7637a8f73341b69b" + }, + { + "file": "refactor/scripts/jassub-vendor-patch.test.mjs", + "sha256": "90c84e52ff0b41472490cbd43deba02d369ea0227da958c1869e25490bf7fb0b" + } + ], + "unit": { + "red": { + "file": "refactor/.cache/jassub08-unit-red.log", + "sha256": "144ca45df393dd694c436945351d896460c11210d87b2c34bef5fa777949e470", + "pass": 5, + "fail": 1 + }, + "green": { + "file": "refactor/.cache/jassub08-unit-green.log", + "sha256": "ce42e8049b4f01ee2934e9ff467cb731e5baa3e01eb48f4c925c418fe50fa8d2", + "pass": 6, + "fail": 0 + }, + "combined": { + "file": "refactor/.cache/jassub08-all.log", + "sha256": "601ad9ca100f9f77677fb4a4df43829d6f001c56c20d7938ecf541a81375c523", + "pass": 191, + "fail": 0 + }, + "source": { + "file": "refactor/.cache/jassub08-candidate-source.log", + "sha256": "41fdea5a226fa592117077dcba21fbed1f4a30acf2bfb3802c66f7a528259d05", + "pass": 74, + "fail": 0 + }, + "main": { + "file": "refactor/.cache/jassub08-candidate-js.log", + "sha256": "002e3b6e444ab4b5d4515d19e1ccfa8c539de2c6431e2173ea551ac6b2e572e3", + "pass": 74, + "fail": 0 + }, + "legacy": { + "file": "refactor/.cache/jassub08-candidate-legacy.js.log", + "sha256": "889aacbfe2584c9f8e6f8f7878d412284d63de8aced97da1cbf8e61e56b3b838", + "pass": 74, + "fail": 0 + } + }, + "browser": { + "passedCandidate": 51, + "reports": [ + { + "file": "refactor/.cache/jassub05-offscreen-main-red.json", + "sha256": "67b606a9c71f4f8f9596e0078c10ade8c4bb74b66e1bd4d59dd1160b09a7040b", + "stats": { + "startTime": "2026-09-13T18:19:26.682Z", + "duration": 56164.22, + "expected": 3, + "skipped": 0, + "unexpected": 6, + "flaky": 0 + }, + "cases": [ + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "failed", + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\fixtures.js", + "column": 48, + "line": 29 + }, + "message": "Error: Unhandled browser errors\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoEqual\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // deep equality\u001b[22m\n\n\u001b[32m- Expected - 1\u001b[39m\n\u001b[31m+ Received + 3\u001b[39m\n\n\u001b[32m- Array []\u001b[39m\n\u001b[31m+ Array [\u001b[39m\n\u001b[31m+ \"this._ctx.clearRect is not a function\",\u001b[39m\n\u001b[31m+ ]\u001b[39m\n\n at fixtures.js:29\n\n 27 | }).catch(() => null)\n 28 | await testInfo.attach('browser-evidence', { contentType: 'application/json', body: JSON.stringify({ browser: browser.version(), platform: process.platform, manifest, state, errors, consoleErrors, failedRequests }, null, 2) })\n> 29 | expect(errors, 'Unhandled browser errors').toEqual([])\n | ^\n 30 | }, { auto: true }],\n 31 | })\n 32 |\n at Object.base.extend.diagnostics.auto (D:\\github\\ArtPlayer\\test\\browser\\fixtures.js:29:48)" + } + ], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.510165, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.016156, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.12965, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 146, + "droppedFrames": 0, + "decodedFrames": 146 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [ + "this._ctx.clearRect is not a function" + ], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "failed", + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\fixtures.js", + "column": 48, + "line": 29 + }, + "message": "Error: Unhandled browser errors\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoEqual\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // deep equality\u001b[22m\n\n\u001b[32m- Expected - 1\u001b[39m\n\u001b[31m+ Received + 3\u001b[39m\n\n\u001b[32m- Array []\u001b[39m\n\u001b[31m+ Array [\u001b[39m\n\u001b[31m+ \"this._ctx.clearRect is not a function\",\u001b[39m\n\u001b[31m+ ]\u001b[39m\n\n at fixtures.js:29\n\n 27 | }).catch(() => null)\n 28 | await testInfo.attach('browser-evidence', { contentType: 'application/json', body: JSON.stringify({ browser: browser.version(), platform: process.platform, manifest, state, errors, consoleErrors, failedRequests }, null, 2) })\n> 29 | expect(errors, 'Unhandled browser errors').toEqual([])\n | ^\n 30 | }, { auto: true }],\n 31 | })\n 32 |\n at Object.base.extend.diagnostics.auto (D:\\github\\ArtPlayer\\test\\browser\\fixtures.js:29:48)" + } + ], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5079, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.014979, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.121651, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 146, + "droppedFrames": 0, + "decodedFrames": 146 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [ + "this._ctx.clearRect is not a function" + ], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "failed", + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\fixtures.js", + "column": 48, + "line": 29 + }, + "message": "Error: Unhandled browser errors\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoEqual\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // deep equality\u001b[22m\n\n\u001b[32m- Expected - 1\u001b[39m\n\u001b[31m+ Received + 3\u001b[39m\n\n\u001b[32m- Array []\u001b[39m\n\u001b[31m+ Array [\u001b[39m\n\u001b[31m+ \"this._ctx.clearRect is not a function\",\u001b[39m\n\u001b[31m+ ]\u001b[39m\n\n at fixtures.js:29\n\n 27 | }).catch(() => null)\n 28 | await testInfo.attach('browser-evidence', { contentType: 'application/json', body: JSON.stringify({ browser: browser.version(), platform: process.platform, manifest, state, errors, consoleErrors, failedRequests }, null, 2) })\n> 29 | expect(errors, 'Unhandled browser errors').toEqual([])\n | ^\n 30 | }, { auto: true }],\n 31 | })\n 32 |\n at Object.base.extend.diagnostics.auto (D:\\github\\ArtPlayer\\test\\browser\\fixtures.js:29:48)" + } + ], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.505108, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.016086, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.128845, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 146, + "droppedFrames": 0, + "decodedFrames": 146 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [ + "this._ctx.clearRect is not a function" + ], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "failed", + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\fixtures.js", + "column": 48, + "line": 29 + }, + "message": "Error: Unhandled browser errors\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoEqual\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // deep equality\u001b[22m\n\n\u001b[32m- Expected - 1\u001b[39m\n\u001b[31m+ Received + 3\u001b[39m\n\n\u001b[32m- Array []\u001b[39m\n\u001b[31m+ Array [\u001b[39m\n\u001b[31m+ \"OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas.\",\u001b[39m\n\u001b[31m+ ]\u001b[39m\n\n at fixtures.js:29\n\n 27 | }).catch(() => null)\n 28 | await testInfo.attach('browser-evidence', { contentType: 'application/json', body: JSON.stringify({ browser: browser.version(), platform: process.platform, manifest, state, errors, consoleErrors, failedRequests }, null, 2) })\n> 29 | expect(errors, 'Unhandled browser errors').toEqual([])\n | ^\n 30 | }, { auto: true }],\n 31 | })\n 32 |\n at Object.base.extend.diagnostics.auto (D:\\github\\ArtPlayer\\test\\browser\\fixtures.js:29:48)" + } + ], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.588799, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 14, + "droppedFrames": 0, + "mozPresentedFrames": 14 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000021, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 0, + "signature": 0, + "width": 640, + "height": 360, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.04052, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 266, + "droppedFrames": 0, + "mozPresentedFrames": 266 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [ + "OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas." + ], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "failed", + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\jassub-native.spec.js", + "column": 83, + "line": 159 + }, + "message": "Error: Timeout 7000ms exceeded while waiting on the predicate\n\n 157 | await page.locator('#play').click()\n 158 | await expect.poll(() => page.evaluate(() => window.jassubPixels().signature)).not.toBe(before.signature)\n> 159 | await expect.poll(() => page.evaluate(() => window.jassubPixels().visible)).toBeGreaterThan(100)\n | ^\n 160 | const after = await page.evaluate(() => window.jassubPixels('after-seek'))\n 161 | expect(after.time).toBeGreaterThanOrEqual(10)\n 162 | expect(after.signature).not.toBe(before.signature)\n at D:\\github\\ArtPlayer\\test\\browser\\jassub-native.spec.js:159:83" + }, + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\fixtures.js", + "column": 48, + "line": 29 + }, + "message": "Error: Unhandled browser errors\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoEqual\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // deep equality\u001b[22m\n\n\u001b[32m- Expected - 1\u001b[39m\n\u001b[31m+ Received + 4\u001b[39m\n\n\u001b[32m- Array []\u001b[39m\n\u001b[31m+ Array [\u001b[39m\n\u001b[31m+ \"OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas.\",\u001b[39m\n\u001b[31m+ \"OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas.\",\u001b[39m\n\u001b[31m+ ]\u001b[39m\n\n at fixtures.js:29\n\n 27 | }).catch(() => null)\n 28 | await testInfo.attach('browser-evidence', { contentType: 'application/json', body: JSON.stringify({ browser: browser.version(), platform: process.platform, manifest, state, errors, consoleErrors, failedRequests }, null, 2) })\n> 29 | expect(errors, 'Unhandled browser errors').toEqual([])\n | ^\n 30 | }, { auto: true }],\n 31 | })\n 32 |\n at Object.base.extend.diagnostics.auto (D:\\github\\ArtPlayer\\test\\browser\\fixtures.js:29:48)" + } + ], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.588183, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 0, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [ + "OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas.", + "OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas." + ], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "failed", + "errors": [ + { + "location": { + "file": "D:\\github\\ArtPlayer\\test\\browser\\fixtures.js", + "column": 48, + "line": 29 + }, + "message": "Error: Unhandled browser errors\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoEqual\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // deep equality\u001b[22m\n\n\u001b[32m- Expected - 1\u001b[39m\n\u001b[31m+ Received + 3\u001b[39m\n\n\u001b[32m- Array []\u001b[39m\n\u001b[31m+ Array [\u001b[39m\n\u001b[31m+ \"OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas.\",\u001b[39m\n\u001b[31m+ ]\u001b[39m\n\n at fixtures.js:29\n\n 27 | }).catch(() => null)\n 28 | await testInfo.attach('browser-evidence', { contentType: 'application/json', body: JSON.stringify({ browser: browser.version(), platform: process.platform, manifest, state, errors, consoleErrors, failedRequests }, null, 2) })\n> 29 | expect(errors, 'Unhandled browser errors').toEqual([])\n | ^\n 30 | }, { auto: true }],\n 31 | })\n 32 |\n at Object.base.extend.diagnostics.auto (D:\\github\\ArtPlayer\\test\\browser\\fixtures.js:29:48)" + } + ], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.569409, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000025, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040435, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "mozPresentedFrames": 16 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [ + "OffscreenCanvas.width setter: Cannot set width of detached OffscreenCanvas." + ], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5454792, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0569792, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4184375, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.3853542 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.6006459, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0605, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4252084, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.4287709 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "d20f3918a60f63476775eb3bdf18730e53364b1499be87f3bec238310e457f3f" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5870626, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.1197709, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4821042, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.4135834 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + } + ] + }, + { + "file": "refactor/.cache/jassub08-offscreen-main.json", + "sha256": "7fa1989e02818cdf5c01fb3b58c8e701c59db190de73407a431c7fe6f2c6afa5", + "stats": { + "startTime": "2026-09-13T18:22:00.588Z", + "duration": 37170.543999999994, + "expected": 9, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.50073, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.014387, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.119052, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 145, + "droppedFrames": 0, + "decodedFrames": 145 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.500226, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.014795, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.02, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.508049, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.016108, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.115017, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 145, + "droppedFrames": 0, + "decodedFrames": 145 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.569471, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000021, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 14, + "droppedFrames": 0, + "mozPresentedFrames": 14 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 0, + "signature": 0, + "width": 640, + "height": 360, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.04064, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 265, + "droppedFrames": 0, + "mozPresentedFrames": 265 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.275483, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 6, + "droppedFrames": 0, + "mozPresentedFrames": 6 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000023, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 8, + "droppedFrames": 0, + "mozPresentedFrames": 8 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040592, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 9, + "droppedFrames": 0, + "mozPresentedFrames": 9 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.58706, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000021, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.041567, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "mozPresentedFrames": 16 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5683334, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0844792, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4574167, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.38 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5967084, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0777292, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.3334376, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.3808959 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.6190001, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.1306459, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4969376, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.4517292 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + } + ] + }, + { + "file": "refactor/.cache/jassub08-offscreen-legacy.json", + "sha256": "6286b17f1885478f2d3d6a766ea522c681d6d4595ebaca737bcefae9e2287852", + "stats": { + "startTime": "2026-09-13T18:23:46.518Z", + "duration": 40890.588, + "expected": 21, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "onDemandRender": true, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.005034, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "getColorSpace" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 0.04 + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 9 + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=false", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "onDemandRender": false, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.005034, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "video", + "rate": 1.5 + }, + { + "target": "video" + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual invalid Worker URL construction releases the newly created canvas and media listeners", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-construction-failure": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "state": { + "error": { + "name": "SyntaxError", + "message": "Failed to construct 'Worker': 'http://[' is not a valid URL." + }, + "activeListeners": 0, + "ownedContainers": 0 + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB native asynchronous CSP Worker error reaches a pending query and explicit destruction cleans up", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-worker-error": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "state": { + "outcome": { + "errorIsNativeEvent": true, + "trusted": true, + "sameNativeError": true, + "type": "error", + "rowsAbsent": true + }, + "calls": 1, + "terminated": 1, + "ownedContainers": 0 + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [ + "Creating a worker from 'http://127.0.0.1:8084/assets/jassub/jassub-worker.js' violates the following Content Security Policy directive: \"worker-src 'none'\". The action has been blocked.", + "Error: [object Event]\n at e._error (:7:17063)\n at _worker.onerror (:7:5023)" + ] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "onDemandRender": true, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 0.04 + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 9 + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=false", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "onDemandRender": false, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video", + "rate": 1.5 + }, + { + "target": "video" + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual invalid Worker URL construction releases the newly created canvas and media listeners", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-construction-failure": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "state": { + "error": { + "name": "SyntaxError", + "message": "Worker constructor: Failed to load worker script at \"http://[\"" + }, + "activeListeners": 0, + "ownedContainers": 0 + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB native asynchronous CSP Worker error reaches a pending query and explicit destruction cleans up", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-worker-error": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "state": { + "outcome": { + "errorIsNativeEvent": true, + "trusted": true, + "sameNativeError": true, + "type": "error", + "rowsAbsent": true + }, + "calls": 1, + "terminated": 1, + "ownedContainers": 0 + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [ + "Error", + "[JavaScript Error: \"Content-Security-Policy: The page’s settings blocked a worker script (worker-src) at http://127.0.0.1:8084/assets/jassub/jassub-worker.js from being executed because it violates the following directive: “worker-src 'none'”\" {file: \"http://127.0.0.1:8084/test/player.html?core=candidate\" line: 0}]" + ] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "onDemandRender": true, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.1591799, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 9 + }, + { + "target": "getEvents" + }, + { + "target": "demand", + "time": 9.154034 + } + ] + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=false", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "onDemandRender": false, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.2022521, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "video", + "rate": 1.5 + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual invalid Worker URL construction releases the newly created canvas and media listeners", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-construction-failure": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "state": { + "error": { + "name": "SyntaxError", + "message": "The string did not match the expected pattern." + }, + "activeListeners": 0, + "ownedContainers": 0 + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB native asynchronous CSP Worker error reaches a pending query and explicit destruction cleans up", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-worker-error": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "state": { + "outcome": { + "errorIsNativeEvent": true, + "trusted": true, + "sameNativeError": true, + "type": "error", + "rowsAbsent": true + }, + "calls": 1, + "terminated": 1, + "ownedContainers": 0 + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [ + "Refused to load http://127.0.0.1:8084/assets/jassub/jassub-worker.js because it does not appear in the worker-src directive of the Content Security Policy.", + "Error: [object Event]" + ] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.500554, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.015614, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.02, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.508032, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.016669, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.121062, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 145, + "droppedFrames": 0, + "decodedFrames": 145 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.484381, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "decodedFrames": 15 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.013742, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 141, + "droppedFrames": 0, + "decodedFrames": 141 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.112778, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 144, + "droppedFrames": 0, + "decodedFrames": 144 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.565244, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000025, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 14, + "droppedFrames": 0, + "mozPresentedFrames": 14 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040299, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.582567, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000023, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040511, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 17, + "droppedFrames": 0, + "mozPresentedFrames": 17 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": true, + "selected": true + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.562413, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.00002, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 14, + "droppedFrames": 0, + "mozPresentedFrames": 14 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040576, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "offscreenCanvas" + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "unbusy" + }, + { + "target": "unbusy" + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5980418, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0567083, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4255209, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.4279376 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.6206876, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.2857084, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.4200001 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c" + }, + "defaultOffscreen": true, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5486459, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0852292, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4479167, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.3870209 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + } + ] + }, + { + "file": "refactor/.cache/jassub08-main-thread.json", + "sha256": "35ffad89e4d40ef3dea516088b7c3fea3d8fa129d29c383d71b1d966d7547a9b", + "stats": { + "startTime": "2026-09-13T18:25:04.769Z", + "duration": 40313.901999999995, + "expected": 21, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=true", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "onDemandRender": true, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.005034, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 9 + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=false", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "onDemandRender": false, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.005034, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "getColorSpace" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "video", + "rate": 1.5 + }, + { + "target": "video" + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual invalid Worker URL construction releases the newly created canvas and media listeners", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-construction-failure": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "state": { + "error": { + "name": "SyntaxError", + "message": "Failed to construct 'Worker': 'http://[' is not a valid URL." + }, + "activeListeners": 0, + "ownedContainers": 0 + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB native asynchronous CSP Worker error reaches a pending query and explicit destruction cleans up", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-worker-error": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "state": { + "outcome": { + "errorIsNativeEvent": true, + "trusted": true, + "sameNativeError": true, + "type": "error", + "rowsAbsent": true + }, + "calls": 1, + "terminated": 1, + "ownedContainers": 0 + } + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [ + "Creating a worker from 'http://127.0.0.1:8084/assets/jassub/jassub-worker.js' violates the following Content Security Policy directive: \"worker-src 'none'\". The action has been blocked.", + "Error: [object Event]\n at e._error (:7:16271)\n at _worker.onerror (:7:4573)" + ] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=true", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "onDemandRender": true, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 0.04 + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 9 + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=false", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "onDemandRender": false, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video", + "rate": 1.5 + }, + { + "target": "video" + }, + { + "target": "getColorSpace" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual invalid Worker URL construction releases the newly created canvas and media listeners", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-construction-failure": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "state": { + "error": { + "name": "SyntaxError", + "message": "Worker constructor: Failed to load worker script at \"http://[\"" + }, + "activeListeners": 0, + "ownedContainers": 0 + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB native asynchronous CSP Worker error reaches a pending query and explicit destruction cleans up", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-worker-error": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "state": { + "outcome": { + "errorIsNativeEvent": true, + "trusted": true, + "sameNativeError": true, + "type": "error", + "rowsAbsent": true + }, + "calls": 1, + "terminated": 1, + "ownedContainers": 0 + } + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [ + "Error", + "[JavaScript Error: \"Content-Security-Policy: The page’s settings blocked a worker script (worker-src) at http://127.0.0.1:8084/assets/jassub/jassub-worker.js from being executed because it violates the following directive: “worker-src 'none'”\" {file: \"http://127.0.0.1:8084/test/player.html?core=candidate\" line: 0}]" + ] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=true", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "onDemandRender": true, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.1389286, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "demand", + "time": 9.0181786 + }, + { + "target": "demand", + "time": 9.0926994 + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual video replacement and repeated destruction, onDemandRender=false", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-lifecycle": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "onDemandRender": false, + "state": { + "parentMatches": true, + "originalContainerCount": 0, + "time": 9.1328441, + "event": { + "Start": 0, + "Duration": 30000, + "ReadOrder": 0, + "Layer": 0, + "Style": 1, + "MarginL": 0, + "MarginR": 0, + "MarginV": 0, + "Name": "", + "Text": "Native lifecycle subtitle", + "Effect": "" + }, + "terminated": 1, + "ownedContainers": 0, + "replacementPreserved": true, + "errors": [], + "sent": [ + { + "target": "init" + }, + { + "target": "canvas" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "canvas" + }, + { + "target": "video" + }, + { + "target": "video", + "rate": 1.5 + }, + { + "target": "video" + }, + { + "target": "video" + }, + { + "target": "getEvents" + } + ] + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB actual invalid Worker URL construction releases the newly created canvas and media listeners", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-construction-failure": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "state": { + "error": { + "name": "SyntaxError", + "message": "The string did not match the expected pattern." + }, + "activeListeners": 0, + "ownedContainers": 0 + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB native asynchronous CSP Worker error reaches a pending query and explicit destruction cleans up", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "jassub-native-worker-error": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "state": { + "outcome": { + "errorIsNativeEvent": true, + "trusted": true, + "sameNativeError": true, + "type": "error", + "rowsAbsent": true + }, + "calls": 1, + "terminated": 1, + "ownedContainers": 0 + } + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [ + "Refused to load http://127.0.0.1:8084/assets/jassub/jassub-worker.js because it does not appear in the worker-src directive of the Content Security Policy.", + "Error: [object Event]" + ] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=false", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": true, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.506552, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.016543, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.115878, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 145, + "droppedFrames": 0, + "decodedFrames": 145 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "demand", + "time": 0.4 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 2, + "width": 640, + "height": 360 + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=false", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": true, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.507383, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.017662, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.121, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 145, + "droppedFrames": 0, + "decodedFrames": 145 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "demand", + "time": 0.4 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 2, + "width": 640, + "height": 360 + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=false", + "project": "chromium", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": true, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.509196, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "decodedFrames": 16 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.018427, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 142, + "droppedFrames": 0, + "decodedFrames": 142 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.120605, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 145, + "droppedFrames": 0, + "decodedFrames": 145 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "demand", + "time": 0.4 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 2, + "width": 640, + "height": 360 + } + ] + } + ] + }, + "browser": { + "version": "153.0.8010.12", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=false", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": true, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.600508, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 14, + "droppedFrames": 0, + "mozPresentedFrames": 14 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000021, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040348, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "mozPresentedFrames": 16 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "demand", + "time": 0.48 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=false", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": true, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.569749, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 13, + "droppedFrames": 0, + "mozPresentedFrames": 13 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000028, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 14, + "droppedFrames": 0, + "mozPresentedFrames": 14 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040266, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "demand", + "time": 0.44 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=false", + "project": "firefox", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": true, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 2676, + "signature": 1690974404, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.581702, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 14, + "droppedFrames": 0, + "mozPresentedFrames": 14 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 6216, + "signature": 3526987101, + "width": 640, + "height": 360, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.000026, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 15, + "droppedFrames": 0, + "mozPresentedFrames": 15 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 22298, + "signature": 2781790832, + "width": 1280, + "height": 720, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.040412, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 16, + "droppedFrames": 0, + "mozPresentedFrames": 16 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "canvas", + "width": 640, + "height": 360 + }, + { + "target": "demand", + "time": 0.48 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "render", + "images": 0, + "width": 640, + "height": 360 + }, + { + "target": "verifyColorSpace" + } + ] + } + ] + }, + "browser": { + "version": "155.0", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with candidate core, customCanvas=false, defaultOffscreen=false", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "candidate", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.6302918, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0745417, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.3411459, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.4833334 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published core, customCanvas=false, defaultOffscreen=false", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.6439376, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0724792, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.4094584, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.4748543 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + }, + { + "title": "JASSUB candidate artifact renders actual WASM subtitles through seek and layout with published-5.3.1-beta.1 core, customCanvas=false, defaultOffscreen=false", + "project": "webkit", + "status": "passed", + "errors": [], + "evidence": { + "playback": { + "core": "published-5.3.1-beta.1", + "source": { + "artifact": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886" + }, + "defaultOffscreen": false, + "selected": { + "available": false, + "selected": false + }, + "resources": [ + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker.js", + "status": 200, + "contentType": "text/javascript" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/jassub-worker-modern.wasm", + "status": 200, + "contentType": "application/wasm" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + }, + { + "url": "http://127.0.0.1:8084/assets/jassub/default.woff2", + "status": 200, + "contentType": "font/woff2" + } + ], + "errors": [], + "snapshots": [ + { + "phase": "before-seek", + "visible": 13152, + "signature": 1263898348, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 0.5463542, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "after-seek", + "visible": 30818, + "signature": 827736580, + "width": 1280, + "height": 720, + "cssWidth": 640, + "cssHeight": 360, + "time": 10.0806875, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + }, + { + "phase": "fullscreen", + "visible": 119170, + "signature": 1826006850, + "width": 2560, + "height": 1440, + "cssWidth": 1280, + "cssHeight": 720, + "time": 10.3820001, + "connected": true, + "media": { + "paused": false, + "readyState": 4, + "totalFrames": 0, + "droppedFrames": 0, + "decodedFrames": 0 + }, + "onDemand": true + } + ], + "workers": [ + { + "terminated": 1, + "sentFirst": [ + { + "target": "init", + "width": 300, + "height": 150 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "canvas", + "width": 1280, + "height": 720 + }, + { + "target": "demand", + "time": 0.3997084 + } + ], + "receivedFirst": [ + { + "target": "ready" + }, + { + "target": "verifyColorSpace" + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 0, + "width": 1280, + "height": 720 + }, + { + "target": "render", + "images": 2, + "width": 1280, + "height": 720 + } + ] + } + ] + }, + "browser": { + "version": "26.6", + "platform": "win32", + "errors": [], + "consoleErrors": [] + } + } + } + ] + } + ], + "boundary": "Windows Playwright actual Worker/WASM/font and canvas pixels. Chromium/Firefox select offscreen; WebKit has no transfer capability and uses the default main-thread fallback. Lifecycle spec keeps explicit offscreenRender=false. No device/GPU endurance/complete hybrid transition acceptance." + }, + "checks": [ + { + "file": "refactor/.cache/jassub08-lint.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "file": "refactor/.cache/jassub08-typecheck.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "file": "refactor/.cache/jassub08-build.log", + "sha256": "ca60ce58bbe559222af46a905c071ff2bf88dea41b4dd459a12184599f3b85aa" + }, + { + "file": "refactor/.cache/jassub08-installed.log", + "sha256": "882d668d221c6b028720efdfd1a1889fe20c677e568624a3357a8aaacce80fdb" + } + ], + "installed": { + "file": "refactor/.cache/jassub-package-types-QtlhaU/report.json", + "sha256": "93546b85f5930b698e603f4644094e8e3289ada8e8f6f11cf3df65fd27c0b407", + "reusedRunnerTask": "PKG-JASSUB-04", + "rootDeclarations": [ + { + "version": "1.0.0", + "candidateSha256": "0c00ce8fd60780c7c01d23534c193cedd32898dc79739e7cf13d8700a6ab7676", + "publishedSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450", + "bytesEqual": false, + "normalizedLFSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450" + }, + { + "version": "1.1.0", + "candidateSha256": "0c00ce8fd60780c7c01d23534c193cedd32898dc79739e7cf13d8700a6ab7676", + "publishedSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450", + "bytesEqual": false, + "normalizedLFSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450" + } + ], + "packages": [ + { + "name": "artplayer", + "archiveSha256": "0c0ea52d41575261b836aefac68280733b119c75834ecad6d4bc78edb073f4c1", + "files": { + "package/ARCHITECTURE.md": "bee98fc9d93a3911d58e98ef15f2dbe07e12f2274c444d989094248a22079e46", + "package/README.md": "1e185e65f67fc2081b4182bbc6c4558ea05b6e3fa3acc5dd0c3ac7df1d542b09", + "package/THIRD_PARTY_NOTICES": "b77b5b46b79fa0cda850b0781f78c3b1112c4ed9672fa291956fe8eff53098e7", + "package/dist/artplayer.js": "6dc8ca6d6eb34aa8a056cbc31328efd634530b3c5c60f0014cb7ce719fabc335", + "package/dist/artplayer.legacy.js": "80f74a8a39df4baf64cc00c65d21cd57c011bfcdead0da38eea077fbc67c5c04", + "package/dist/artplayer.mjs": "432e2b0ad92009a09743e020bf7c928c8b8f18a52496622b16259ec9ab20059f", + "package/dist/i18n/ar.js": "bd0bef65f4f7dc3f8ed562904cc6fa9071ff4537fb64c1e0fc3d554141bcd3cb", + "package/dist/i18n/ar.mjs": "59310b7bbeea83bbb7d73aadc5ca82a6ec269c3530d19aa741c94d5c64fc5da8", + "package/dist/i18n/cs.js": "6e2c93daba24c2e48dfa206bcf4f2f2a8a02713b856e404d2e4e4ecd8309ca2f", + "package/dist/i18n/cs.mjs": "c73fba18797d62d7b2581e67fe7340c35fe84510b2250ff1ecaad253d9cabbac", + "package/dist/i18n/es.js": "f4133ac6ea06b69a474b33c4a1809a4066e2376bb9464a3f3aa8330f01f1944a", + "package/dist/i18n/es.mjs": "1390bca3def2be115e811de337df0a0c3f63998e51359f283023246245c552a7", + "package/dist/i18n/fa.js": "8d3ef2e0f0cc0ea480c2167b6fcb87cdf444e90759c3519e8daa139fec576da4", + "package/dist/i18n/fa.mjs": "ab441e8a2d79043b29ceca87c783bf06874bb9d3a149c1604bc167eb481be2a9", + "package/dist/i18n/fr.js": "89dc4194a6c0a962b9ce756b52c90401c1acf3b159f265f3bc0d7d6d7d987f03", + "package/dist/i18n/fr.mjs": "99491878430fb7b6f2b7bf93da0588a831704b412e01116f23ba1d9d45863816", + "package/dist/i18n/id.js": "4c6dc86db741bcc2857df55a9d037e82e91d375fa6fd22e0562809ff621b92db", + "package/dist/i18n/id.mjs": "383e5803a6b6686c6de4e867770241de75b6f517dcca2bdedc6f2004bf6e1fb3", + "package/dist/i18n/pl.js": "3a38828b1c3d719c0aca9906cf6a46c23555a8411f8d57645f0e0ce8147dc664", + "package/dist/i18n/pl.mjs": "079ed96732979035297af387c64a7b99519b5a43107fb86735a654ea4fe8e9b5", + "package/dist/i18n/ru.js": "62fac9dddb302eb16382e6e9301fc4b2c66f5f69d4a358a26b67026a5fa4e787", + "package/dist/i18n/ru.mjs": "a893aeaee1d79409db72e324fbff200e3864f33ed168f04d91d25f7cf2efa765", + "package/dist/i18n/tr.js": "1492c36b069a7d73db4f3913bd18085faff7afd8b3c158138fe264e31600e38c", + "package/dist/i18n/tr.mjs": "a90478cac078836b76c2a98261907610fee07f3e4b28671b8e7dbf533778f918", + "package/dist/i18n/vi.js": "c7216ef7e608a79b7e2c479a07bf310d4ab79577947ac4a62d676faaced0e9cf", + "package/dist/i18n/vi.mjs": "66270fdfa0b5da396322d1769169b7df37a030ba15ac18eb30bd87b3af8074ec", + "package/dist/i18n/zh-tw.js": "11c49857d6d40a5ffd224ffa59c9026e71621b345f63c5a086326db80a22371a", + "package/dist/i18n/zh-tw.mjs": "a38e630cb96de96c15d824686aec750e25cf6c8ada01285a292442a81566314f", + "package/package.json": "82e92699e7c29847f32ac6767ece0401290e7d7a12854722bdbcfd09b90b7954", + "package/types/COMPATIBILITY.md": "a7da9e102a116104b513df4f7451247b7759bc502d3375f30bd5b14a541826e0", + "package/types/README.md": "1bd9868e773610e6312fd48a1c5aa20772d29df0af40c3db66e75b7ab4a1aee0", + "package/types/artplayer.d.cts": "3685065e4263abcfd9d953176e461d5b3eb990b0363b54689a7f55deba770fef", + "package/types/artplayer.d.mts": "b664fec51ee5c5381f2ceab25d99d52aee56feab04a2ee7b4ea5b2145ea5fa0e", + "package/types/artplayer.d.ts": "5d0162adf7ac6d0f2bb9b5cfe361f28657c4d9c540cadbf36eba3cc954ce50f8", + "package/types/component.d.ts": "ae5bc1ddeaa1ee1ebbc62573e32423993727079205c64751a5a314170e588a32", + "package/types/config.d.ts": "36f9a84cd436f17701a0d11d3417fc1fe0414e0c52c80083b94a85dfc329e37e", + "package/types/cssVar.d.ts": "93217860fff2ebf750f606d95ddd22220a58837119e63bdf2f5f78fd7488458b", + "package/types/emitter.d.ts": "7e1f9a2a8ce65feb95734f1ed52d1334e57aa388bbef2a43d8bc53a9b6f6623c", + "package/types/events.d.ts": "f83624c9268a284477e8bd793fe3562a2363b72f2a44d5c64fe8c6a6cede8830", + "package/types/i18n.d.ts": "f4f2f05bdfda73c74fef34767cb18ee8e11b743120b1c4598e9714d7846018e5", + "package/types/icons.d.ts": "326a67ba7bdcf52862c5b2a269e540140aff98d05c7b96196485a77f84fe5960", + "package/types/language.d.cts": "f7928e108cf7b7814c2d75cb0a525333e95873fca6cd6d89a740450656b9c1cd", + "package/types/language.d.mts": "6619a26d604b7cccbe2f596243d87ae37cfaae33b8b52874ec071d9787446f9e", + "package/types/legacy/language.d.ts": "c7abda4d506fd933c350e9030290bf9e64347a921d683a66115da1995ebe0a81", + "package/types/option.d.ts": "ccf2c8ddc537dc65c9682d39f044726e23bff18f476b622512d7e6a4b949b5f6", + "package/types/playback.d.ts": "58705c273df6e76a77a6575e769a9ec6c013785c25080f2551aa22415788d870", + "package/types/player.d.ts": "92b00211b70ac71336e495899df972a0519dd138111846044fe4e0f967966177", + "package/types/plugin.d.ts": "fc3594a41c51d8248713e33c486fb1f6a518ac5c7ce31be6988a6cd8d052c5f3", + "package/types/quality.d.ts": "1ac1a48b4f74ff9ba1ce60443e1463d50d1c6a2e5d87d63dc7d2a8eb7f4c2c34", + "package/types/runtime.d.cts": "7ee988dfea9a0ac71a34a656f96f7b74e78aa92547cfdfab7ff7e1139a77d4a3", + "package/types/runtime.d.mts": "dcb85f59a8b7714918ced0c1d18c2bb24e8b80b56d8c594e019dcbdb5ad88b08", + "package/types/runtime.d.ts": "9c6ccd39a1be293f17ae46dae8ea077053e12635ee79d73a5e3b3a559230fcff", + "package/types/runtime/component.d.ts": "1b4c0cee44568649e80140fe778febfcae88af0ac85515f1cbeff78ab0c6d14f", + "package/types/runtime/construction.d.ts": "7a87bedf6f7ffff0c46078aa5f1551e0077d35574e286516121f5f935e2d9ce4", + "package/types/runtime/events.d.ts": "a1e2f9d387475453eaf95c2a5ee79e228636c0bb859bda3fcc46da46574a0c31", + "package/types/runtime/media.d.ts": "8fc89401be7fe25542c169d07dd5675f10916ed20be8493e19695966cf3864a8", + "package/types/runtime/option.d.ts": "6e334e1a76fdcc40b4665c02523bd31c3994d96078fadeb40e23422aa54c1a1d", + "package/types/runtime/player.d.ts": "8ac6383502e4872e83659838844856903031a81a0adc8e8535feb78453aa042c", + "package/types/runtime/plugin.d.ts": "8528f2b17843149f42f9cc16d6fd70baa238c9dc2c329b67d2c38096799c69bd", + "package/types/runtime/services.d.ts": "604c9f8e4b6c0da818f96576bf9f4b0e96085a9003927b2f7ba30027b1ba237e", + "package/types/runtime/setting.d.ts": "349c1fcb205ad312916bd3ee55e6bf241ea8a569fb2ab6c80822e69fc518f7d7", + "package/types/runtime/subtitle.d.ts": "269ff84678d327b3a9dc2f5bc6cc0d731d1e081b85422e474621d5d792efb153", + "package/types/runtime/template.d.ts": "7a62f968a38b4bf9109a4439557c02074eb1d62ba1f6e21a8eb194e91f0badfe", + "package/types/runtime/utils.d.ts": "6bf731705d86853e066dbaf3b8d4003b6548423fe615b7412b722bd0d3a6e48b", + "package/types/setting.d.ts": "08305a75dff96f06490430e099338b463df471b550c1d0dac3abc8995b39eb09", + "package/types/subtitle.d.ts": "b18314e2d64efdb6045830b6e12f615ae2ed585416130e562329ad3ea337f6ce", + "package/types/template.d.ts": "4792bc0c2cbcb7966e4375118bd34b326166e0831862e94ace4cf6b1bbe6a8c8", + "package/types/utils.d.ts": "fca0d3d814df94a25f9eb067c86fa0cf272e2791bac793b91229d57680797712" + } + }, + { + "name": "artplayer-plugin-jassub", + "archiveSha256": "3880d8704739b5227078bb1e2093047114e9336f834669fde9a1d587022efbc8", + "files": { + "package/ARCHITECTURE.md": "f0b17937d59a80f33843533c3b858aaa5f3bc31110c352be2286a7cf186445e3", + "package/README.md": "06ec53e11a1aed27c978987a126781874e569e6f211d712ee7021f776d7ea10b", + "package/dist/artplayer-plugin-jassub.js": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "package/dist/artplayer-plugin-jassub.legacy.js": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "package/dist/artplayer-plugin-jassub.mjs": "1208c560cf9ae104903b052741098f9e4d37a5d0057bb28f29168cf245c79782", + "package/package.json": "e5098c03fb59c920ba28318348ffa5573e162d38293d0ac39c4fd74f9ee70c9b", + "package/types/README.md": "bc8e2943831aad7022c2ce0ae1cde704284da043857d5aa4acdd3fa161da63dd", + "package/types/artplayer-plugin-jassub.d.ts": "0c00ce8fd60780c7c01d23534c193cedd32898dc79739e7cf13d8700a6ab7676", + "package/types/runtime-api.d.ts": "ece90385f39c3d3dc648476bfd798dc42348c8f050742a8226870136add5cd5b", + "package/types/runtime.d.cts": "b4557e2016dd21b6ef34206ed3116e8879afe16a59ed85eaf1618846539b24bd", + "package/types/runtime.d.mts": "6ca863aed785caa1f2707ddfc4cb8456bed2465dbb0a2a1bc12e949a2ffccadc", + "package/types/runtime.d.ts": "b4557e2016dd21b6ef34206ed3116e8879afe16a59ed85eaf1618846539b24bd", + "package/worker/jassub-worker-modern.wasm": "8a8b37463713d1f2ddbc1fbb8a35889d9565e5a6670851758b46b2216d8e513c", + "package/worker/jassub-worker.js": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707", + "package/worker/jassub-worker.wasm": "73880d99ba9260ac39fc4476491cf254ca784c76f3af2fb03f3f9be8065ad3c0" + } + } + ], + "matrix": [ + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations.\n There are types at '/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.cts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "raw": [ + { + "code": 2344, + "file": "consumer.mts", + "line": 10, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 18, + "message": "Type '(_option: JassubOption) => (_art: Artplayer) => { name: string; instance: JassubInstance; }' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 19, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' is not assignable to type 'OldFactory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(option: JassubOption): (art: Artplayer) => OldResult'." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 22, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.mts", + "line": 32, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 33, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 34, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 35, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 36, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 37, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 38, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "bundler-esm", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations.\n There are types at '/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.cts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "raw": [ + { + "code": 2344, + "file": "consumer.mts", + "line": 10, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 18, + "message": "Type '(_option: JassubOption) => (_art: Artplayer) => { name: string; instance: JassubInstance; }' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 19, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' is not assignable to type 'OldFactory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(option: JassubOption): (art: Artplayer) => OldResult'." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 22, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.mts", + "line": 32, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 33, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 34, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 35, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 36, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 37, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 38, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "bundler-esm", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.ts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.ts", + "node_modules/artplayer/types/artplayer.d.ts", + "node_modules/artplayer/types/component.d.ts", + "node_modules/artplayer/types/config.d.ts", + "node_modules/artplayer/types/cssVar.d.ts", + "node_modules/artplayer/types/emitter.d.ts", + "node_modules/artplayer/types/events.d.ts", + "node_modules/artplayer/types/i18n.d.ts", + "node_modules/artplayer/types/icons.d.ts", + "node_modules/artplayer/types/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.d.ts", + "node_modules/artplayer/types/quality.d.ts", + "node_modules/artplayer/types/setting.d.ts", + "node_modules/artplayer/types/subtitle.d.ts", + "node_modules/artplayer/types/template.d.ts", + "node_modules/artplayer/types/utils.d.ts" + ], + "sourceSha256": "f5e31a263c5b2793182ac9ebde944ba589f6a09b15547eeb568c6ffbf228d81a" + } + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.cts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.cts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.cts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.cts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.cts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.cts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.cts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.cts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.cts", + "node_modules/artplayer/types/artplayer.d.cts", + "node_modules/artplayer/types/artplayer.d.ts", + "node_modules/artplayer/types/component.d.ts", + "node_modules/artplayer/types/config.d.ts", + "node_modules/artplayer/types/cssVar.d.ts", + "node_modules/artplayer/types/emitter.d.ts", + "node_modules/artplayer/types/events.d.ts", + "node_modules/artplayer/types/i18n.d.ts", + "node_modules/artplayer/types/icons.d.ts", + "node_modules/artplayer/types/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.d.ts", + "node_modules/artplayer/types/quality.d.ts", + "node_modules/artplayer/types/setting.d.ts", + "node_modules/artplayer/types/subtitle.d.ts", + "node_modules/artplayer/types/template.d.ts", + "node_modules/artplayer/types/utils.d.ts" + ], + "sourceSha256": "f5e31a263c5b2793182ac9ebde944ba589f6a09b15547eeb568c6ffbf228d81a", + "commonjs": { + "esModuleInterop": false, + "diagnostics": [], + "declarations": [ + "consumer.cts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.cts", + "node_modules/artplayer/types/artplayer.d.cts", + "node_modules/artplayer/types/artplayer.d.ts", + "node_modules/artplayer/types/component.d.ts", + "node_modules/artplayer/types/config.d.ts", + "node_modules/artplayer/types/cssVar.d.ts", + "node_modules/artplayer/types/emitter.d.ts", + "node_modules/artplayer/types/events.d.ts", + "node_modules/artplayer/types/i18n.d.ts", + "node_modules/artplayer/types/icons.d.ts", + "node_modules/artplayer/types/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.d.ts", + "node_modules/artplayer/types/quality.d.ts", + "node_modules/artplayer/types/setting.d.ts", + "node_modules/artplayer/types/subtitle.d.ts", + "node_modules/artplayer/types/template.d.ts", + "node_modules/artplayer/types/utils.d.ts" + ], + "sourceSha256": "bdfbbfdc72847fcc44ee5a605b9e1a55f4452f84f85aa12f5991eaa7ba4092c5" + } + } + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "raw": [ + { + "code": 2344, + "file": "consumer.mts", + "line": 10, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 18, + "message": "Type '(_option: JassubOption) => (_art: Artplayer) => { name: string; instance: JassubInstance; }' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 19, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' is not assignable to type 'OldFactory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(option: JassubOption): (art: Artplayer) => OldResult'." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 22, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.mts", + "line": 32, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 33, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 34, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 35, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 36, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 37, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 38, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.mts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.mts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.mts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.mts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.mts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.mts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.mts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.mts", + "node_modules/artplayer/types/artplayer.d.cts", + "node_modules/artplayer/types/artplayer.d.mts", + "node_modules/artplayer/types/artplayer.d.ts", + "node_modules/artplayer/types/component.d.ts", + "node_modules/artplayer/types/config.d.ts", + "node_modules/artplayer/types/cssVar.d.ts", + "node_modules/artplayer/types/emitter.d.ts", + "node_modules/artplayer/types/events.d.ts", + "node_modules/artplayer/types/i18n.d.ts", + "node_modules/artplayer/types/icons.d.ts", + "node_modules/artplayer/types/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.d.ts", + "node_modules/artplayer/types/quality.d.ts", + "node_modules/artplayer/types/setting.d.ts", + "node_modules/artplayer/types/subtitle.d.ts", + "node_modules/artplayer/types/template.d.ts", + "node_modules/artplayer/types/utils.d.ts" + ], + "sourceSha256": "f5e31a263c5b2793182ac9ebde944ba589f6a09b15547eeb568c6ffbf228d81a" + } + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "bundler-esm", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.ts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.mts", + "node_modules/artplayer/types/artplayer.d.cts", + "node_modules/artplayer/types/artplayer.d.mts", + "node_modules/artplayer/types/artplayer.d.ts", + "node_modules/artplayer/types/component.d.ts", + "node_modules/artplayer/types/config.d.ts", + "node_modules/artplayer/types/cssVar.d.ts", + "node_modules/artplayer/types/emitter.d.ts", + "node_modules/artplayer/types/events.d.ts", + "node_modules/artplayer/types/i18n.d.ts", + "node_modules/artplayer/types/icons.d.ts", + "node_modules/artplayer/types/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.d.ts", + "node_modules/artplayer/types/quality.d.ts", + "node_modules/artplayer/types/setting.d.ts", + "node_modules/artplayer/types/subtitle.d.ts", + "node_modules/artplayer/types/template.d.ts", + "node_modules/artplayer/types/utils.d.ts" + ], + "sourceSha256": "f5e31a263c5b2793182ac9ebde944ba589f6a09b15547eeb568c6ffbf228d81a" + } + }, + { + "plugin": "candidate", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string | undefined'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 76, + "message": "Argument of type '{ typoOption: boolean; }' is not assignable to parameter of type 'RuntimeOption'.\n Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 78, + "message": "Argument of type 'true' is not assignable to parameter of type 'number | undefined'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number | undefined'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.ts", + "node_modules/artplayer/types/artplayer.d.ts", + "node_modules/artplayer/types/component.d.ts", + "node_modules/artplayer/types/config.d.ts", + "node_modules/artplayer/types/cssVar.d.ts", + "node_modules/artplayer/types/emitter.d.ts", + "node_modules/artplayer/types/events.d.ts", + "node_modules/artplayer/types/i18n.d.ts", + "node_modules/artplayer/types/icons.d.ts", + "node_modules/artplayer/types/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.d.ts", + "node_modules/artplayer/types/quality.d.ts", + "node_modules/artplayer/types/setting.d.ts", + "node_modules/artplayer/types/subtitle.d.ts", + "node_modules/artplayer/types/template.d.ts", + "node_modules/artplayer/types/utils.d.ts" + ], + "sourceSha256": "f5e31a263c5b2793182ac9ebde944ba589f6a09b15547eeb568c6ffbf228d81a", + "commonjs": { + "esModuleInterop": false, + "diagnostics": [], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.ts", + "node_modules/artplayer/types/artplayer.d.ts", + "node_modules/artplayer/types/component.d.ts", + "node_modules/artplayer/types/config.d.ts", + "node_modules/artplayer/types/cssVar.d.ts", + "node_modules/artplayer/types/emitter.d.ts", + "node_modules/artplayer/types/events.d.ts", + "node_modules/artplayer/types/i18n.d.ts", + "node_modules/artplayer/types/icons.d.ts", + "node_modules/artplayer/types/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.d.ts", + "node_modules/artplayer/types/quality.d.ts", + "node_modules/artplayer/types/setting.d.ts", + "node_modules/artplayer/types/subtitle.d.ts", + "node_modules/artplayer/types/template.d.ts", + "node_modules/artplayer/types/utils.d.ts" + ], + "sourceSha256": "bdfbbfdc72847fcc44ee5a605b9e1a55f4452f84f85aa12f5991eaa7ba4092c5" + } + } + } + ], + "scope": "Actual npm 1.0.0/1.1.0 and Yarn-packed candidate/core installed outside workspace; offline installation and forced frozen reinstall with unchanged lock, strictly verified installed member hashes and non-link checks; root declaration text unchanged after CRLF normalization with both raw hashes recorded, exact old diagnostics, conditional accurate runtime declarations and Node lazy factory/legacy identity. Registrars are never invoked in Node; this is not browser Worker/WASM/font rendering or publication acceptance." + }, + "artifacts": [ + { + "file": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "b1b0d3a1900a1bbb05bce5270926f15254e210d90064701546de95deb6fcd886", + "bytes": 18427, + "gzip": 6069, + "previousBytes": 18325, + "previousGzip": 6045, + "docsEqual": true + }, + { + "file": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "bd9bc96d556edb2c89c773bb65f9c23faf64d011b4a880b276d6168eda28c00c", + "bytes": 19363, + "gzip": 6411, + "previousBytes": 19261, + "previousGzip": 6385, + "docsEqual": true + }, + { + "file": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.mjs", + "sha256": "1208c560cf9ae104903b052741098f9e4d37a5d0057bb28f29168cf245c79782", + "bytes": 38649, + "gzip": 11150, + "previousBytes": 38509, + "previousGzip": 11117, + "docsEqual": true + } + ], + "preserved": "Default options, resource payloads, Worker JS/WASM/fonts, declarations, independent package versions and public method return types unchanged. Only initial offscreen transfer is prioritized before opening the loaded gate. Later detach/reattach is unchanged.", + "remaining": [ + "PKG-JASSUB-05 complete combination/device/failure-recovery/hybrid validation", + "PKG-JASSUB-06 distribution and VENDOR-04/05 notices", + "All project major versions, CI/CD and release reviews remain required" + ] +} diff --git a/refactor/baselines/jassub-offscreen.patch b/refactor/baselines/jassub-offscreen.patch new file mode 100644 index 000000000..a880ba9ef --- /dev/null +++ b/refactor/baselines/jassub-offscreen.patch @@ -0,0 +1,24 @@ +diff --git a/packages/artplayer-plugin-jassub/src/jassub.es.js b/packages/artplayer-plugin-jassub/src/jassub.es.js +index 904b40888..6bd2bc2c6 100644 +--- a/packages/artplayer-plugin-jassub/src/jassub.es.js ++++ b/packages/artplayer-plugin-jassub/src/jassub.es.js +@@ -143,7 +143,7 @@ class o extends EventTarget { + // @ts-ignore + useLocalFonts: typeof queryLocalFonts < "u" && (e.useLocalFonts ?? !0), + hasBitmapBug: o._hasBitmapBug +- }), this._offscreenRender === !0 && this.sendMessage("offscreenCanvas", null, [this._canvasctrl]); ++ }); + }).catch((error) => { + if (!this._destroyed) this.destroy(error); + }); +@@ -580,6 +580,10 @@ class o extends EventTarget { + } + _ready() { + if (this._destroyed) return; ++ if (this._offscreenRender === !0 && !this._initialOffscreenSent) { ++ this._initialOffscreenSent = true; ++ this._worker.postMessage({ target: "offscreenCanvas", transferable: [this._canvasctrl] }, [this._canvasctrl]); ++ } + this._init(), this.dispatchEvent(new CustomEvent("ready")); + } + /** diff --git a/refactor/changes/2026-09-14-PKG-JASSUB-08-offscreen.md b/refactor/changes/2026-09-14-PKG-JASSUB-08-offscreen.md new file mode 100644 index 000000000..a960b0b7c --- /dev/null +++ b/refactor/changes/2026-09-14-PKG-JASSUB-08-offscreen.md @@ -0,0 +1,78 @@ +# PKG-JASSUB-08 默认 offscreen 初始化修复 + +## 问题与实现 + +从 `0f3c068aae1415c2d40ede8708f02f4c5864fe7a` 开始补全 05 默认模式验收时, +Chromium/Firefox 三个核心组合都出现真实页面异常: +`this._ctx.clearRect is not a function`。WebKit 本机没有转移能力,默认回退路径 +三项通过。这是 3 通过/6 失败的实际结果,不是浏览器连接或媒体网络问题。 + +Worker 消息证明初始化顺序为 init → canvas → offscreenCanvas。构造时 setVideo +已排队 resize,等待 `_loaded`;初始画布转移后来才排队。ready 解锁时,Worker +先执行 resize,在尚未接收画布时向主线程发回 render。主线程已选 offscreen, +`_ctx=false`,因此空图像消息也会触发 clearRect 异常。字幕随后能够出现不能 +抵消这个未处理错误。 + +本修复只调整初始归属交接:Worker ready 到达后先同步 postMessage 转移画布, +再 resolve `_loaded` 并派发公开 ready。标志阻止重复 ready 转移同一画布两次。 +于是所有排队的 resize、track 和 ready 监听器消息在画布交接之后到达 Worker。 +已销毁实例仍由现有终态检查拦截。没有全局禁用 offscreen,也不静默吞掉 render +异常;后续 hybrid detach/reattach 保持原样,其完整组合仍属 05。 + +API-04/05/10/12:公开注册和实例方法同步返回值、选项默认、资源 URL、Worker +载荷和文件均保留,仅修复内部消息顺序。自有 TS 与公共声明不变。无新依赖、 +锁文件、版本或运行时目标变化。JASSUB 的原始及 07 来源指纹保留,08 新增 +[独立补丁](../baselines/jassub-offscreen.patch)和[补丁记录](../baselines/jassub-offscreen-patch.json)。 +校验器沿两个已记录基线验证补丁链,核对旧补丁的实际 Git diff、新补丁可逆性和 +最终 source 指纹,不覆盖历史证据。包内 ARCHITECTURE.md 同步初始化顺序及复跑方式。 + +## 测试和真实证据 + +[验证记录](../baselines/jassub-offscreen-validation.json)记录本次源码/产物/测试 +指纹、失败与通过报告、原生消息顺序、像素快照和最终安装矩阵。 + +| 验证 | 结果 | +| --- | --- | +| 新增六项顺序与选择测试 | 修复前 5 通过/1 失败,候选 6 通过;另五项保护重复 ready、提前销毁、显式 false、无能力和自定义 canvas | +| 联合 JASSUB | 191 项通过,含历史缺陷基线与新的候选测试,不把全部数量当成新增修复 | +| 源码/main/legacy | 各 74 项通过;类型未变,严格分包 TS 及 lint 通过 | +| 默认模式 main | 9 项通过:三个浏览器 × 候选核心/实际 5.4.0/实际 5.3.1-beta.1 | +| 默认模式 legacy + 生命周期 | 21 项通过,其中默认模式 9 项,显式主线程生命周期 12 项 | +| main 显式主线程 + 生命周期 | 21 项通过,其中播放 9 项、生命周期 12 项 | +| 实际安装 | 15 个当前/旧编译器矩阵通过,准确入口逐条 14 负例及无 interop 消费;核心 68 和插件 15 个打包成员与最终工作区一致 | + +共 51 项候选真实浏览器验证,零跳过、零重试通过。实际版本为 Windows Playwright +Chromium 153.0.8010.12、Firefox 155.0、WebKit 26.6。前两者记录 available/selected +均 true,WebKit 两者均 false;不能称为三个引擎都验证了 offscreen。 + +测试读取显示画布的真实 bitmap 到独立 canvas,避免对已经转移的画布调用 +getContext;未替换 Worker、WASM、字体或视频解码。仍逐项断言字幕透明像素数量、 +seek 前后像素签名变化、播放位置、网页全屏尺寸和销毁次数,且默认能力选择必须 +与平台吻合。原六项失败保留为红色证据,新实现不以放宽页面异常检查获得通过。 + +正常构建三格式及 docs 副本相同。main gzip 从 6,045 到 6,069 字节(+24), +legacy 从 6,385 到 6,411(+26)。安装证据复用 04 的 runner,记录保留原 task +字段,本次验证明确归属 08。包文档更新后才运行最终 pack,没有混用旧候选。 + +## 复跑与后续 + +```sh +yarn test:jassub +yarn test:jassub-types-package +yarn build artplayer-plugin-jassub +node --test test/jassub-offscreen.test.js +node --test refactor/scripts/jassub-vendor-patch.test.mjs +``` + +使用固定 Node/Yarn;设置 ARTPLAYER_JASSUB_ARTIFACT 为正常 main/legacy 文件, +ARTPLAYER_JASSUB_OFFSCREEN=default 后执行 +`yarn test:browser test/browser/jassub-native.spec.js --workers=1`。 +不设置该 offscreen 变量时仍验证显式主线程路径。每次浏览器运行后先归档共享报告。 + +关闭 JASSUB-OFFSCREEN-01,新增独立 08 任务与提交,作为 05 的前置。05 仍未完成: +全量切源/hybrid、错误恢复、真实设备与持续 GPU/内存释放不能由上述窗口测试证明。 +06 的分发/通知和 VENDOR-04/05 保留,所有包 major、CI/CD、三轮复盘不受影响。 +没有 push、tag 或 npm 发布。 + +回退本 commit 并正常构建恢复 07,保留其生命周期/字幕时钟修复;补丁链校验器 +随同回退。不要对运行中的 Worker 热替换画布协议。 diff --git a/refactor/plan.md b/refactor/plan.md index a7c7efe16..13543d670 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -2,9 +2,9 @@ > 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。 -基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 232 项,范围 22 个包及工作区/示例。 +基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 233 项,范围 22 个包及工作区/示例。 -状态:todo 62 / doing 14 / blocked 0 / done 156 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 62 / doing 14 / blocked 0 / done 157 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -27,7 +27,7 @@ | artplayer-plugin-dash-control | 1.1.0 | PKG-DASH-01, PKG-DASH-02, PKG-DASH-03, PKG-DASH-04, PKG-DASH-05, PKG-DASH-06 | | artplayer-plugin-document-pip | 1.1.0 | PKG-DPIP-01, PKG-DPIP-02, PKG-DPIP-03, PKG-DPIP-04, PKG-DPIP-05, PKG-DPIP-06 | | artplayer-plugin-hls-control | 1.1.0 | PKG-HLS-01, PKG-HLS-02, PKG-HLS-03, PKG-HLS-04, PKG-HLS-SDK-01, PKG-HLS-05, PKG-HLS-06 | -| artplayer-plugin-jassub | 1.1.0 | PKG-JASSUB-01, PKG-JASSUB-02, PKG-JASSUB-03, PKG-JASSUB-04, PKG-JASSUB-05, PKG-JASSUB-06, PKG-JASSUB-07 | +| artplayer-plugin-jassub | 1.1.0 | PKG-JASSUB-01, PKG-JASSUB-02, PKG-JASSUB-03, PKG-JASSUB-04, PKG-JASSUB-05, PKG-JASSUB-06, PKG-JASSUB-07, PKG-JASSUB-08 | | artplayer-plugin-multiple-subtitles | 1.2.0 | PKG-MULTI-SUB-01, PKG-MULTI-SUB-02, PKG-MULTI-SUB-03, PKG-MULTI-SUB-04, PKG-MULTI-SUB-07, PKG-MULTI-SUB-05, PKG-MULTI-SUB-06 | | artplayer-plugin-vast | 1.2.0 | PKG-VAST-01, PKG-VAST-02, PKG-VAST-03, PKG-VAST-04, PKG-VAST-05, PKG-VAST-06 | | artplayer-plugin-vtt-thumbnail | 1.1.0 | PKG-VTT-THUMB-01, PKG-VTT-THUMB-02, PKG-VTT-THUMB-03, PKG-VTT-THUMB-04, PKG-VTT-THUMB-05, PKG-VTT-THUMB-06 | @@ -233,9 +233,10 @@ | PKG-JASSUB-02 | artplayer-plugin-jassub
建立特有行为与错误测试 | PKG-JASSUB-01, ENG-03, ENG-05 | ASS 字体、时钟/seek/倍率/resize、加载失败和销毁 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | | PKG-JASSUB-03 | artplayer-plugin-jassub
整理内部职责与资源 | PKG-JASSUB-02, CORE-15, CORE-16 | 仅整理自有 adapter/销毁;保留第三方文件及来源 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done | | PKG-JASSUB-04 | artplayer-plugin-jassub
迁移自有源码和公开类型 | PKG-JASSUB-03, ENG-04, ENG-06, CORE-07 | JASSUB option/instance 的兼容类型包装,vendor JS 例外记录 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | done | -| PKG-JASSUB-05 | artplayer-plugin-jassub
验证新旧核心和组合 | PKG-JASSUB-04, CORE-22, PKG-JASSUB-07 | 真实 worker/WASM 字幕渲染与全屏、旧核心测试 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | +| PKG-JASSUB-05 | artplayer-plugin-jassub
验证新旧核心和组合 | PKG-JASSUB-04, CORE-22, PKG-JASSUB-07, PKG-JASSUB-08 | 真实 worker/WASM 字幕渲染与全屏、旧核心测试 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | | PKG-JASSUB-06 | artplayer-plugin-jassub
验证分发并同步文档 | PKG-JASSUB-05, ENG-07 | jassub.js、外部资源路径、许可和离线失败记录;接续 VENDOR-04/05 完整组件/字体通知、LGPL 源码分发核对及六份未明确字体的分发处置 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录;来源身份已由01冻结,完整通知和未明确字体的发布处理必须闭环,不能以来源相同替代许可结论 | H | todo | | PKG-JASSUB-07 | artplayer-plugin-jassub
修复 vendor 生命周期与字幕时钟 | PKG-JASSUB-03, PKG-JASSUB-02 | 独立记录 vendor 适配差异;幂等销毁、跨容器 setVideo、构造回滚、逐帧归属和倍率/能力边界;查询 timeout/Worker error 的缺失数据回调及每请求监听器/定时器清理(JASSUB-QUERY-01) | 保持公开真实 instance、同步方法与资源路径;保留原 vendor 来源指纹并记录每项实际补丁;候选修复正例和真实字幕/失败/时钟验证通过,未证实设备不得冒充通过 | H | done | +| PKG-JASSUB-08 | artplayer-plugin-jassub
修复默认 offscreen 初始化消息顺序 | PKG-JASSUB-07 | 在释放排队绘制消息前转移初始画布;独立 vendor 补丁、默认模式原生回归和维护文档 | 保留默认能力选择、Worker/资源和公开同步 API;旧红新绿消息顺序测试及真实默认 offscreen 播放/seek/全屏通过,主线程绘制保持 | H | done | ## 5 包迁移:artplayer-plugin-danmuku-mask @@ -602,3 +603,4 @@ - PKG-DANMUKU-10: [记录](changes/2026-09-13-PKG-DANMUKU-10-heatmap-density.md) [记录](baselines/danmuku-heatmap-density-validation.json) - PKG-DANMUKU-11: [记录](changes/2026-09-13-PKG-DANMUKU-11-visible-lifetime.md) [记录](baselines/danmuku-lifetime-validation.json) - PKG-DANMUKU-12: [记录](changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md) [记录](baselines/danmuku-frame-sampling-validation.json) +- PKG-JASSUB-08: [记录](changes/2026-09-14-PKG-JASSUB-08-offscreen.md) [记录](baselines/jassub-offscreen-validation.json) [记录](baselines/jassub-offscreen-patch.json) diff --git a/refactor/progress.md b/refactor/progress.md index 683fa8f01..3fd4e612e 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,17 @@ # 进度与证据 +## PKG-JASSUB-08 默认 offscreen 初始化完成 + +05 默认模式验收发现 Chromium/Firefox 六项真实页面错误;初始 canvas 消息先于 +offscreenCanvas,使 Worker 返回主线程无法绘制的 render。现在先交接画布再打开 +ready 门槛,保留原能力选择,新增六项顺序/取消/回退测试(旧 5 通过/1 失败)。 +联合 191 项、源码/main/legacy 各 74 项通过;默认 main、默认 legacy 加生命周期、 +显式主线程加生命周期共 51 项原生验证通过。15 个安装类型矩阵和最终包成员一致。 +[变更与复跑](changes/2026-09-14-PKG-JASSUB-08-offscreen.md)及 +[证据](baselines/jassub-offscreen-validation.json)保留失败与修复,关闭 +JASSUB-OFFSCREEN-01。08 独立交付;05 保留全量组合、hybrid/错误恢复/设备等验收, +06、VENDOR-04/05、独立 major 与全局发布复盘均未完成。 + ## PKG-JASSUB-07 vendor 生命周期与默认字幕时钟完成 独立补丁保留原上游身份,修复幂等销毁、构造回滚、跨视频帧归属、数值倍率和 diff --git a/refactor/risk-table.md b/refactor/risk-table.md index 67b2d9b00..8233824b0 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -249,3 +249,4 @@ | JASSUB-RATE-01 | resolved / 已复现 | Fallback ratechange sends an Event instead of numeric playbackRate | PKG-JASSUB-02, PKG-JASSUB-07 | | JASSUB-NATIVE-FRAME-01 | resolved / 已复现 | Windows WebKit default frame-clock path does not produce subtitle demands in actual playback | PKG-JASSUB-02, PKG-JASSUB-07, PKG-JASSUB-05 | | JASSUB-QUERY-01 | resolved / 已复现 | Subtitle query errors throw before calling the consumer and leave request listeners attached | PKG-JASSUB-07, PKG-JASSUB-05 | +| JASSUB-OFFSCREEN-01 | resolved / 已复现 | Default offscreen initialization lets queued resize render before Worker canvas ownership, raising clearRect on false context | PKG-JASSUB-08, PKG-JASSUB-05 | diff --git a/refactor/risks.json b/refactor/risks.json index f60f445b8..4fba1c168 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -5599,6 +5599,28 @@ "test/browser/jassub-lifecycle.spec.js" ], "resolutionRationale": "Actual wrapper timeout and Worker error invoke once with the original error and clean all request listeners/timers first, including throwing user callbacks. Native CSP plain Event identity is preserved; real WASM queries still succeed. Destroy cancellation settles all pending queries after cleanup; complete error recovery remains task05." + }, + { + "id": "JASSUB-OFFSCREEN-01", + "title": "Default offscreen initialization lets queued resize render before Worker canvas ownership, raising clearRect on false context", + "confirmation": "reproduced", + "status": "resolved", + "owners": [ + "PKG-JASSUB-08", + "PKG-JASSUB-05" + ], + "evidence": [ + "test/jassub-offscreen.test.js", + "test/browser/jassub-native.spec.js" + ], + "compatibleResolution": "Transfer the initial canvas after Worker readiness but before releasing queued rendering; preserve selected offscreen/default and all worker resources.", + "closureCriteria": "Same ordering test fails on the pre-fix artifact and passes on candidate; actual default offscreen pixels, seek/layout and teardown pass on Chromium/Firefox and capability fallback on WebKit, with main-thread regressions retained.", + "resolutionEvidence": [ + "refactor/changes/2026-09-14-PKG-JASSUB-08-offscreen.md", + "refactor/baselines/jassub-offscreen-validation.json", + "test/jassub-offscreen.test.js" + ], + "resolutionRationale": "Controlled queue test reproduces pre-fix canvas-before-transfer order. Candidate transfers before opening readiness and passes actual default offscreen Chromium/Firefox playback/seek/layout; Windows WebKit default capability fallback and explicit main-thread/lifecycle regressions remain green. Full device/hybrid/error recovery remains task05." } ] } diff --git a/refactor/scripts/jassub-vendor-patch.test.mjs b/refactor/scripts/jassub-vendor-patch.test.mjs index 2c4460c3f..a980688c1 100644 --- a/refactor/scripts/jassub-vendor-patch.test.mjs +++ b/refactor/scripts/jassub-vendor-patch.test.mjs @@ -8,15 +8,21 @@ import { hash } from './releases.mjs' test('JASSUB local vendor patch retains its exact original, changed source and reversible patch identity', () => { const record = JSON.parse(fs.readFileSync('refactor/baselines/jassub-vendor-patch.json', 'utf8')) const original = execFileSync('git', ['show', `${record.baselineCommit}:${record.file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n') - const current = fs.readFileSync(record.file, 'utf8').replaceAll('\r\n', '\n') + const followUp = JSON.parse(fs.readFileSync('refactor/baselines/jassub-offscreen-patch.json', 'utf8')) + const current = execFileSync('git', ['show', `${followUp.baselineCommit}:${record.file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n') const patch = fs.readFileSync(record.patchFile, 'utf8').replaceAll('\r\n', '\n') assert.equal(hash(original), record.originalSha256LF) assert.equal(hash(current), record.patchedSha256LF) assert.equal(hash(patch), record.patchSha256LF) assert.notEqual(record.originalSha256LF, record.patchedSha256LF) - execFileSync('git', ['apply', '--check', '--reverse', '--ignore-space-change', record.patchFile], { stdio: 'pipe' }) + const committedPatch = execFileSync('git', ['diff', '--no-ext-diff', record.baselineCommit, followUp.baselineCommit, '--', record.file], { encoding: 'utf8' }).replaceAll('\r\n', '\n') + assert.equal(hash(committedPatch), record.patchSha256LF) + assert.equal(followUp.originalSha256LF, record.patchedSha256LF) + assert.equal(hash(fs.readFileSync(record.file, 'utf8').replaceAll('\r\n', '\n')), followUp.patchedSha256LF) + assert.equal(hash(fs.readFileSync(followUp.patchFile, 'utf8').replaceAll('\r\n', '\n')), followUp.patchSha256LF) + execFileSync('git', ['apply', '--check', '--reverse', '--ignore-space-change', followUp.patchFile], { stdio: 'pipe' }) const registry = JSON.parse(fs.readFileSync('refactor/third-party.json', 'utf8')) const group = registry.vendored.find(item => item.id === 'jassub-code-and-workers') assert.equal(group.localPatch.originalSha256LF, record.originalSha256LF) - assert.equal(group.fingerprints.find(item => item.path === record.file).sha256, record.patchedSha256LF) + assert.equal(group.fingerprints.find(item => item.path === record.file).sha256, followUp.patchedSha256LF) }) diff --git a/refactor/tasks.json b/refactor/tasks.json index b092074cf..1f466ae3d 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -2496,7 +2496,8 @@ "dependsOn": [ "PKG-JASSUB-04", "CORE-22", - "PKG-JASSUB-07" + "PKG-JASSUB-07", + "PKG-JASSUB-08" ], "status": "todo", "risk": "H", @@ -4769,6 +4770,26 @@ "changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md", "baselines/danmuku-frame-sampling-validation.json" ] + }, + { + "id": "PKG-JASSUB-08", + "phase": "5 包迁移:artplayer-plugin-jassub", + "title": "修复默认 offscreen 初始化消息顺序", + "scope": [ + "artplayer-plugin-jassub" + ], + "dependsOn": [ + "PKG-JASSUB-07" + ], + "status": "done", + "risk": "H", + "deliverable": "在释放排队绘制消息前转移初始画布;独立 vendor 补丁、默认模式原生回归和维护文档", + "acceptance": "保留默认能力选择、Worker/资源和公开同步 API;旧红新绿消息顺序测试及真实默认 offscreen 播放/seek/全屏通过,主线程绘制保持", + "evidence": [ + "changes/2026-09-14-PKG-JASSUB-08-offscreen.md", + "baselines/jassub-offscreen-validation.json", + "baselines/jassub-offscreen-patch.json" + ] } ] } diff --git a/refactor/third-party.json b/refactor/third-party.json index 31c2a223e..976f47e83 100644 --- a/refactor/third-party.json +++ b/refactor/third-party.json @@ -354,7 +354,8 @@ "owners": [ "PKG-JASSUB-01", "PKG-JASSUB-06", - "PKG-JASSUB-07" + "PKG-JASSUB-07", + "PKG-JASSUB-08" ], "sourceStatus": "Original wrapper matched npm 1.8.8; PKG-JASSUB-07 now carries an explicitly recorded local lifecycle/clock/query patch (baselines/jassub-vendor-patch.json). Worker JS is unchanged. Both WASM binaries still exactly match Pages nightly 747e392d7f6fe7c38bbcdfe05c9ada46b0b62daf/source 6b19a04ddfbad8f9bfd3237395788dd76218841b. Original wrapper hash, unchanged binaries/fonts, pinned build and submodules remain separately recorded; no independent WASM rebuild.", "licenseStatus": "Matching source LICENSE and nightly COPYRIGHT identified and byte-verified; full component notice assembly, LGPL source/distribution review and full FreeType license remain PKG-JASSUB-06 gates. VENDOR-04 remains open.", @@ -386,7 +387,7 @@ { "path": "packages/artplayer-plugin-jassub/src/jassub.es.js", "algorithm": "sha256-lf", - "sha256": "1fdcf24d206e8711348dddcb5fe7b656007a9b1d81a992bb497c6d10bd0a2cdb" + "sha256": "6a96af7914f702eb7d6303b466cbe16abddd278040f60cd29f153cdf60e92cb2" }, { "path": "packages/artplayer-plugin-jassub/worker/jassub-worker-modern.wasm", @@ -408,7 +409,8 @@ "task": "PKG-JASSUB-07", "record": "refactor/baselines/jassub-vendor-patch.json", "originalSha256LF": "b973508ade00b5b9cea2f299d49f4943003372729be7350b6938e44fddb32038", - "patchedSha256LF": "1fdcf24d206e8711348dddcb5fe7b656007a9b1d81a992bb497c6d10bd0a2cdb" + "patchedSha256LF": "1fdcf24d206e8711348dddcb5fe7b656007a9b1d81a992bb497c6d10bd0a2cdb", + "followUp": "refactor/baselines/jassub-offscreen-patch.json" } }, { diff --git a/test/browser/jassub-native.spec.js b/test/browser/jassub-native.spec.js index 228ba387c..a13e8fb0f 100644 --- a/test/browser/jassub-native.spec.js +++ b/test/browser/jassub-native.spec.js @@ -11,6 +11,7 @@ const artifact = process.env.ARTPLAYER_JASSUB_ARTIFACT const customCanvas = process.env.ARTPLAYER_JASSUB_CUSTOM_CANVAS === 'true' const code = artifact ? fs.readFileSync(artifact, 'utf8') : readMember(archive, member).toString() const onDemandRender = process.env.ARTPLAYER_JASSUB_ON_DEMAND !== 'false' +const defaultOffscreen = process.env.ARTPLAYER_JASSUB_OFFSCREEN === 'default' const subtitles = `[Script Info] ScriptType: v4.00+ PlayResX: 640 @@ -25,7 +26,7 @@ Dialogue: 0,0:00:05.00,0:00:30.00,Default,,0,0,0,,After seek with actual WASM ` for (const core of ['candidate', 'published', 'published-5.3.1-beta.1']) { - test(`JASSUB ${artifact ? 'candidate artifact' : `published ${release.version}`} renders actual WASM subtitles through seek and layout with ${core} core, customCanvas=${customCanvas}`, async ({ page, context }, testInfo) => { + test(`JASSUB ${artifact ? 'candidate artifact' : `published ${release.version}`} renders actual WASM subtitles through seek and layout with ${core} core, customCanvas=${customCanvas}, defaultOffscreen=${defaultOffscreen}`, async ({ page, context }, testInfo) => { const resources = [] const external = [] const origin = new URL(testInfo.project.use.baseURL).origin @@ -86,7 +87,7 @@ for (const core of ['candidate', 'published', 'published-5.3.1-beta.1']) { await page.locator('#play').click() await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(0.1) await page.locator('#pause').click() - await page.evaluate(async ({ subContent, onDemandRender, customCanvas }) => { + await page.evaluate(async ({ subContent, onDemandRender, customCanvas, defaultOffscreen }) => { const register = window.artplayerPluginJassub.default || window.artplayerPluginJassub let canvas if (customCanvas) { @@ -104,20 +105,26 @@ for (const core of ['candidate', 'published', 'published-5.3.1-beta.1']) { modernWasmUrl: '/assets/jassub/jassub-worker-modern.wasm', availableFonts: { 'liberation sans': '/assets/jassub/default.woff2' }, fonts: ['/assets/jassub/default.woff2'], - offscreenRender: false, + ...(defaultOffscreen ? {} : { offscreenRender: false }), onDemandRender, ...(canvas ? { canvas } : {}), })) window.jassub = window.art.plugins.artplayerPluginJassub.instance + window.jassubNative.offscreen = { available: 'transferControlToOffscreen' in HTMLCanvasElement.prototype, selected: window.jassub._offscreenRender } window.jassub.addEventListener('error', event => window.jassubNative.errors.push(String(event.error))) await new Promise((resolve, reject) => { window.jassub.addEventListener('ready', resolve, { once: true }) window.jassub.addEventListener('error', event => reject(event.error), { once: true }) }) + const readback = document.createElement('canvas') window.jassubPixels = (phase) => { const canvas = window.jassub._canvas const rect = canvas.getBoundingClientRect() - const pixels = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data + readback.width = canvas.width + readback.height = canvas.height + const context = readback.getContext('2d') + context.drawImage(canvas, 0, 0) + const pixels = context.getImageData(0, 0, readback.width, readback.height).data let visible = 0 let signature = 0 for (let i = 3; i < pixels.length; i += 4) { @@ -134,7 +141,9 @@ for (const core of ['candidate', 'published', 'published-5.3.1-beta.1']) { window.jassubNative.snapshots.push(state) return state } - }, { subContent: subtitles, onDemandRender, customCanvas }) + }, { subContent: subtitles, onDemandRender, customCanvas, defaultOffscreen }) + const offscreen = await page.evaluate(() => window.jassubNative.offscreen) + expect(offscreen.selected).toBe(defaultOffscreen && !customCanvas && offscreen.available) await page.locator('#play').click() await expect.poll(() => page.evaluate(() => window.jassubPixels().visible)).toBeGreaterThan(100) const before = await page.evaluate(() => window.jassubPixels('before-seek')) @@ -172,7 +181,7 @@ for (const core of ['candidate', 'published', 'published-5.3.1-beta.1']) { } finally { const state = await page.evaluate(() => window.jassubNative).catch(error => ({ unavailable: error.message })) - await testInfo.attach('actual-jassub-evidence', { body: JSON.stringify({ core, onDemandRender, customCanvas, source: artifact ? { artifact, sha256: hash(code) } : { version: release.version, integrity: release.integrity, member, sha256: hash(code) }, subtitleSha256: hash(subtitles), resources, external, state, limitation: 'Actual worker, WASM and local font with offscreenRender=false. No default offscreen path, failure recovery or device acceptance; candidate adds direct-then-host destruction.' }, null, 2), contentType: 'application/json' }) + await testInfo.attach('actual-jassub-evidence', { body: JSON.stringify({ core, onDemandRender, customCanvas, defaultOffscreen, source: artifact ? { artifact, sha256: hash(code) } : { version: release.version, integrity: release.integrity, member, sha256: hash(code) }, subtitleSha256: hash(subtitles), resources, external, state, limitation: `Actual worker, WASM and local font; offscreen option ${defaultOffscreen ? 'omitted, actual capability/selection recorded' : 'explicitly false'}. Canvas pixels are read from a separate canvas copying the native display bitmap. No full failure recovery, sustained GPU/memory or physical-device acceptance; candidate adds direct-then-host destruction.` }, null, 2), contentType: 'application/json' }) if (!page.isClosed()) { await page.evaluate(() => { if (window.art && !window.art.isDestroy) diff --git a/test/jassub-offscreen.test.js b/test/jassub-offscreen.test.js new file mode 100644 index 000000000..ac2fc0173 --- /dev/null +++ b/test/jassub-offscreen.test.js @@ -0,0 +1,69 @@ +import assert from 'node:assert/strict' +// eslint-disable-next-line test/no-import-node-test -- Offscreen protocol ordering needs deterministic queue coverage. +import test from 'node:test' +import { jassubCandidate, jassubEnvironment } from './helpers/jassub.js' + +const candidate = await jassubCandidate() +function environment(offscreen = true) { + const code = `${candidate.code}\nObject.defineProperty(module.exports.default || module.exports, '__canvasClass', { value: HTMLCanvasElement });` + const env = jassubEnvironment({ ...candidate, code }) + const transferred = [] + if (offscreen) { + env.factory.__canvasClass.prototype.transferControlToOffscreen = function () { + const canvas = { width: this.width, height: this.height } + transferred.push(canvas) + return canvas + } + } + return { ...env, transferred } +} + +test('JASSUB initializes offscreen ownership before queued resize, track and ready-listener messages', async () => { + const env = environment() + const { instance } = env.factory()(env.art) + instance.resize(640, 360) + instance.setTrack('[Script Info]') + instance.addEventListener('ready', () => instance.resize(320, 180)) + await env.ready() + const messages = env.workers[0].messages + assert.deepEqual(messages.slice(0, 2).map(message => message.target), ['init', 'offscreenCanvas']) + assert.equal(messages[1].transferable[0], env.transferred[0]) + assert(messages.slice(2).some(message => message.target === 'canvas')) + assert(messages.slice(2).some(message => message.target === 'setTrack')) + assert.equal(instance._ctx, false) + instance.destroy() +}) + +test('JASSUB duplicate readiness does not transfer the initial offscreen canvas twice', async () => { + const env = environment() + const { instance } = env.factory()(env.art) + await env.ready() + await env.ready() + assert.equal(env.workers[0].messages.filter(message => message.target === 'offscreenCanvas').length, 1) + instance.destroy() +}) + +test('JASSUB destroy before readiness never transfers its offscreen canvas', async () => { + const env = environment() + const { instance } = env.factory()(env.art) + instance.destroy() + await env.flush() + instance._ready() + await env.flush() + assert.equal(env.workers[0].messages.length, 0) + assert.equal(env.workers[0].terminated, 1) +}) + +for (const option of [{ offscreenRender: false }, 'unsupported', 'custom']) { + test(`JASSUB main-thread canvas has no initial transfer for ${JSON.stringify(option)}`, async () => { + const env = environment(option !== 'unsupported') + const options = option === 'custom' ? { canvas: env.createCanvas() } : typeof option === 'object' ? option : {} + const { instance } = env.factory(options)(env.art) + await env.ready() + instance.resize(640, 360) + await env.flush() + assert.equal(env.workers[0].messages.some(message => message.target === 'offscreenCanvas'), false) + assert.equal(instance._ctx, instance._canvas.context) + instance.destroy() + }) +}