From 426c0c5d4209aa91be7414b810f1e8dca712c297 Mon Sep 17 00:00:00 2001 From: Harvey Zhao Date: Sun, 13 Sep 2026 03:51:26 +0800 Subject: [PATCH] fix(thumbnail): [PKG-TOOL-THUMB-03] own input resources and separate sheet export --- docs/compiled/artplayer-tool-thumbnail.js | 2 +- .../artplayer-tool-thumbnail.legacy.js | 2 +- docs/compiled/artplayer-tool-thumbnail.mjs | 268 +- package.json | 4 +- .../artplayer-tool-thumbnail/ARCHITECTURE.md | 70 + packages/artplayer-tool-thumbnail/README.md | 2 + .../dist/artplayer-tool-thumbnail.js | 2 +- .../dist/artplayer-tool-thumbnail.legacy.js | 2 +- .../dist/artplayer-tool-thumbnail.mjs | 268 +- .../artplayer-tool-thumbnail/src/index.js | 143 +- .../artplayer-tool-thumbnail/src/input.js | 102 + .../artplayer-tool-thumbnail/src/sheet.js | 50 + .../baselines/thumbnail-input-checkpoint.json | 12667 ++++++++++++++++ ...9-13-PKG-TOOL-THUMB-03-input-checkpoint.md | 71 + refactor/plan.md | 5 +- refactor/progress.md | 12 + refactor/risks.json | 9 +- refactor/tasks.json | 7 +- test/browser/thumbnail-input.spec.js | 56 + test/browser/thumbnail-tool.spec.js | 11 +- test/helpers/thumbnail.js | 9 + test/thumbnail-input.test.js | 218 + 22 files changed, 13724 insertions(+), 256 deletions(-) create mode 100644 packages/artplayer-tool-thumbnail/ARCHITECTURE.md create mode 100644 packages/artplayer-tool-thumbnail/src/input.js create mode 100644 packages/artplayer-tool-thumbnail/src/sheet.js create mode 100644 refactor/baselines/thumbnail-input-checkpoint.json create mode 100644 refactor/changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md create mode 100644 test/browser/thumbnail-input.spec.js create mode 100644 test/thumbnail-input.test.js diff --git a/docs/compiled/artplayer-tool-thumbnail.js b/docs/compiled/artplayer-tool-thumbnail.js index e16cbeccd..32c840117 100644 --- a/docs/compiled/artplayer-tool-thumbnail.js +++ b/docs/compiled/artplayer-tool-thumbnail.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;n{this.errorHandle("number"===typeof this.option[t],`The '${t}' is not a number`)}),this.option.number=e(n,10,1e3),this.option.width=e(o,10,1e3),this.option.column=e(s,1,1e3),this}static creatVideo(){const t=document.createElement("video");return t.style.position="absolute",t.style.top="-9999px",t.style.left="-9999px",t.muted=!0,t.controls=!0,document.body.appendChild(t),t}inputChange(t){const e=this.option.fileInput.files[0];this.loadVideo(e),t.target.value=""}loadVideo(t){if(t){const e=this.video.canPlayType(t.type);this.errorHandle("maybe"===e||"probably"===e,`Playback of this file format is not supported: ${t.type}`);const i=URL.createObjectURL(t);this.videoUrl=i,this.file=t,this.emit("file",this.file),this.video.src=i,this.emit("video",this.video)}}start(){if(!this.video.duration)return(t=1e3,new Promise(e=>setTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const d=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(p=d,p.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var p}creatScreenshotDate(){const{number:t,width:e,height:i,column:n,begin:o}=this.option,s=this.duration/t,r=[o+s];for(;r.length({time:t-s/2,x:o%n*e,y:Math.floor(o/n)*i}))}creatCanvas(){const{number:t,width:e,height:i,column:n}=this.option,o=document.createElement("canvas"),s=o.getContext("2d");return o.width=e*n,o.height=Math.ceil(t/n)*i+30,s.fillStyle="black",s.fillRect(0,0,o.width,o.height),s.font="14px Georgia",s.fillStyle="#fff",s.fillText(`From: https://artplayer.org/, Number: ${t}, Width: ${e}, Height: ${i}, Column: ${n}`,10,o.height-11),o}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=document.createElement("a"),e=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(this.file.name)}.png`;return t.download=e,t.href=this.thumbnailUrl,document.body.appendChild(t),t.click(),document.body.removeChild(t),this.emit("download",e),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){this.option.fileInput.removeEventListener("change",this.inputChange),this.option.fileInput.removeEventListener("dragover",i.ondragover),this.option.fileInput.removeEventListener("drop",i.ondrop),document.body.removeChild(this.video),this.videoUrl&&URL.revokeObjectURL(this.videoUrl),this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.emit("destroy")}}return i}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;nsetTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const c=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(d=c,d.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var d}creatScreenshotDate(){return function(t,e){const{number:i,width:n,height:o,column:s,begin:r}=t,h=e/i,a=[r+h];for(;a.length({time:t-h/2,x:e%s*n,y:Math.floor(e/s)*o}))}(this.option,this.duration)}creatCanvas(){return function(t){const{number:e,width:i,height:n,column:o}=t,s=document.createElement("canvas"),r=s.getContext("2d");return s.width=i*o,s.height=Math.ceil(e/o)*n+30,r.fillStyle="black",r.fillRect(0,0,s.width,s.height),r.font="14px Georgia",r.fillStyle="#fff",r.fillText(`From: https://artplayer.org/, Number: ${e}, Width: ${i}, Height: ${n}, Column: ${o}`,10,s.height-11),s}(this.option)}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=function(t,e){const i=document.createElement("a"),n=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(t.name)}.png`;i.download=n,i.href=e;try{document.body.appendChild(i),i.click()}finally{i.parentNode&&i.parentNode.removeChild(i)}return n}(this.file,this.thumbnailUrl);return this.emit("download",t),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){if(r.has(this))return;let t;r.add(this);for(const i of[()=>s(this),()=>this.video.parentNode?.removeChild(this.video),()=>this.videoUrl&&URL.revokeObjectURL(this.videoUrl),()=>this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),()=>this.emit("destroy")])try{i()}catch(e){t||(t=e)}if(t)throw t}}return h}); diff --git a/docs/compiled/artplayer-tool-thumbnail.legacy.js b/docs/compiled/artplayer-tool-thumbnail.legacy.js index e16cbeccd..42395657e 100644 --- a/docs/compiled/artplayer-tool-thumbnail.legacy.js +++ b/docs/compiled/artplayer-tool-thumbnail.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;n{this.errorHandle("number"===typeof this.option[t],`The '${t}' is not a number`)}),this.option.number=e(n,10,1e3),this.option.width=e(o,10,1e3),this.option.column=e(s,1,1e3),this}static creatVideo(){const t=document.createElement("video");return t.style.position="absolute",t.style.top="-9999px",t.style.left="-9999px",t.muted=!0,t.controls=!0,document.body.appendChild(t),t}inputChange(t){const e=this.option.fileInput.files[0];this.loadVideo(e),t.target.value=""}loadVideo(t){if(t){const e=this.video.canPlayType(t.type);this.errorHandle("maybe"===e||"probably"===e,`Playback of this file format is not supported: ${t.type}`);const i=URL.createObjectURL(t);this.videoUrl=i,this.file=t,this.emit("file",this.file),this.video.src=i,this.emit("video",this.video)}}start(){if(!this.video.duration)return(t=1e3,new Promise(e=>setTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const d=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(p=d,p.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var p}creatScreenshotDate(){const{number:t,width:e,height:i,column:n,begin:o}=this.option,s=this.duration/t,r=[o+s];for(;r.length({time:t-s/2,x:o%n*e,y:Math.floor(o/n)*i}))}creatCanvas(){const{number:t,width:e,height:i,column:n}=this.option,o=document.createElement("canvas"),s=o.getContext("2d");return o.width=e*n,o.height=Math.ceil(t/n)*i+30,s.fillStyle="black",s.fillRect(0,0,o.width,o.height),s.font="14px Georgia",s.fillStyle="#fff",s.fillText(`From: https://artplayer.org/, Number: ${t}, Width: ${e}, Height: ${i}, Column: ${n}`,10,o.height-11),o}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=document.createElement("a"),e=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(this.file.name)}.png`;return t.download=e,t.href=this.thumbnailUrl,document.body.appendChild(t),t.click(),document.body.removeChild(t),this.emit("download",e),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){this.option.fileInput.removeEventListener("change",this.inputChange),this.option.fileInput.removeEventListener("dragover",i.ondragover),this.option.fileInput.removeEventListener("drop",i.ondrop),document.body.removeChild(this.video),this.videoUrl&&URL.revokeObjectURL(this.videoUrl),this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.emit("destroy")}}return i}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;nsetTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const c=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(d=c,d.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var d}creatScreenshotDate(){return function(t,e){const{number:i,width:n,height:o,column:s,begin:r}=t,h=e/i,a=[r+h];for(;a.length({time:t-h/2,x:e%s*n,y:Math.floor(e/s)*o}))}(this.option,this.duration)}creatCanvas(){return function(t){const{number:e,width:i,height:n,column:o}=t,s=document.createElement("canvas"),r=s.getContext("2d");return s.width=i*o,s.height=Math.ceil(e/o)*n+30,r.fillStyle="black",r.fillRect(0,0,s.width,s.height),r.font="14px Georgia",r.fillStyle="#fff",r.fillText(`From: https://artplayer.org/, Number: ${e}, Width: ${i}, Height: ${n}, Column: ${o}`,10,s.height-11),s}(this.option)}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=function(t,e){const i=document.createElement("a"),n=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(t.name)}.png`;i.download=n,i.href=e;try{document.body.appendChild(i),i.click()}finally{i.parentNode&&i.parentNode.removeChild(i)}return n}(this.file,this.thumbnailUrl);return this.emit("download",t),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){if(r.has(this))return;let t;r.add(this);for(const i of[()=>s(this),()=>{var t;return null==(t=this.video.parentNode)?void 0:t.removeChild(this.video)},()=>this.videoUrl&&URL.revokeObjectURL(this.videoUrl),()=>this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),()=>this.emit("destroy")])try{i()}catch(e){t||(t=e)}if(t)throw t}}return h}); diff --git a/docs/compiled/artplayer-tool-thumbnail.mjs b/docs/compiled/artplayer-tool-thumbnail.mjs index f0eab6e03..4d0159c08 100644 --- a/docs/compiled/artplayer-tool-thumbnail.mjs +++ b/docs/compiled/artplayer-tool-thumbnail.mjs @@ -58,19 +58,166 @@ function getFileName(name) { function clamp(num, a, b) { return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); } +const inputs = /* @__PURE__ */ new WeakMap(); +function release(record) { + let failure; + for (const [name, callback] of record.listeners.splice(0)) { + try { + record.input.removeEventListener(name, callback); + } catch (error) { + failure || (failure = error); + } + } + if (record.wrapper) { + try { + if (record.input.parentNode) + record.input.parentNode.removeChild(record.input); + } catch (error) { + failure || (failure = error); + } + if (record.wrapper.style.position === "relative") + record.wrapper.style.position = record.position; + } + if (failure) + throw failure; +} +function connect(record, callbacks) { + try { + for (const [name, callback] of callbacks) { + record.listeners.push([name, callback]); + record.input.addEventListener(name, callback); + } + } catch (error) { + try { + release(record); + } catch { + } + throw error; + } +} +function setupInput(tool, patch) { + const option = Object.assign({}, tool.option, patch); + const target = option.fileInput; + tool.errorHandle(target instanceof Element, "The 'fileInput' is not a Element"); + for (const name of ["number", "width", "column", "begin", "end"]) + tool.errorHandle(typeof option[name] === "number", `The '${name}' is not a number`); + option.number = clamp(option.number, 10, 1e3); + option.width = clamp(option.width, 10, 1e3); + option.column = clamp(option.column, 1, 1e3); + const previous = inputs.get(tool); + if (previous && (target === previous.input || target === previous.wrapper)) { + option.fileInput = previous.input; + return option; + } + const record = { input: target, wrapper: null, position: "", listeners: [], callbacks: previous?.callbacks || null }; + try { + if (!(target.tagName === "INPUT" && target.type === "file")) { + record.wrapper = target; + record.position = target.style.position; + record.input = document.createElement("input"); + record.input.type = "file"; + Object.assign(record.input.style, { position: "absolute", width: "100%", height: "100%", left: "0", top: "0", right: "0", bottom: "0", opacity: "0" }); + target.style.position = "relative"; + target.appendChild(record.input); + } + if (record.callbacks) + connect(record, record.callbacks); + } catch (error) { + try { + release(record); + } catch { + } + throw error; + } + option.fileInput = record.input; + inputs.set(tool, record); + tool.option = option; + if (previous) + release(previous); + return option; +} +function connectInput(tool, dragover) { + const record = inputs.get(tool); + record.callbacks = [["change", tool.inputChange], ["dragover", dragover], ["drop", tool.ondrop]]; + connect(record, record.callbacks); +} +function releaseInput(tool) { + const record = inputs.get(tool); + if (!record) + return; + inputs.delete(tool); + release(record); +} +function screenshotPoints(option, duration) { + const { number, width, height, column, begin } = option; + const timeGap = duration / number; + const timePoints = [begin + timeGap]; + while (timePoints.length < number) { + const last = timePoints[timePoints.length - 1]; + timePoints.push(last + timeGap); + } + return timePoints.map((item, index) => ({ + time: item - timeGap / 2, + x: index % column * width, + y: Math.floor(index / column) * height + })); +} +function createSheet(option) { + const { number, width, height, column } = option; + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + canvas.width = width * column; + canvas.height = Math.ceil(number / column) * height + 30; + context.fillStyle = "black"; + context.fillRect(0, 0, canvas.width, canvas.height); + context.font = "14px Georgia"; + context.fillStyle = "#fff"; + context.fillText( + `From: https://artplayer.org/, Number: ${number}, Width: ${width}, Height: ${height}, Column: ${column}`, + 10, + canvas.height - 11 + ); + return canvas; +} +function downloadSheet(file, url) { + const link = document.createElement("a"); + const name = `${getFileName(file.name)}.png`; + link.download = name; + link.href = url; + try { + document.body.appendChild(link); + link.click(); + } finally { + if (link.parentNode) + link.parentNode.removeChild(link); + } + return name; +} +const destroyed = /* @__PURE__ */ new WeakSet(); class ArtplayerToolThumbnail extends Emitter { constructor(option = {}) { super(); this.processing = false; this.option = {}; - this.setup(Object.assign({}, ArtplayerToolThumbnail.DEFAULTS, option)); - this.video = ArtplayerToolThumbnail.creatVideo(); - this.duration = 0; - this.inputChange = this.inputChange.bind(this); - this.ondrop = this.ondrop.bind(this); - this.option.fileInput.addEventListener("change", this.inputChange); - this.option.fileInput.addEventListener("dragover", ArtplayerToolThumbnail.ondragover); - this.option.fileInput.addEventListener("drop", ArtplayerToolThumbnail.ondrop); + try { + this.setup(Object.assign({}, ArtplayerToolThumbnail.DEFAULTS, option)); + this.video = ArtplayerToolThumbnail.creatVideo(); + this.duration = 0; + this.inputChange = this.inputChange.bind(this); + this.ondrop = this.ondrop.bind(this); + connectInput(this, ArtplayerToolThumbnail.ondragover); + } catch (error) { + try { + releaseInput(this); + } catch { + } + try { + if (this.video?.parentNode) + this.video.parentNode.removeChild(this.video); + } catch { + } + throw error; + } } static get DEFAULTS() { return { @@ -86,35 +233,15 @@ class ArtplayerToolThumbnail extends Emitter { event.preventDefault(); } ondrop(event) { + if (destroyed.has(this)) + return; event.preventDefault(); const file = event.dataTransfer.files[0]; this.loadVideo(file); } setup(option = {}) { - this.option = Object.assign({}, this.option, option); - const { fileInput, number, width, column } = this.option; - this.errorHandle(fileInput instanceof Element, "The 'fileInput' is not a Element"); - if (!(fileInput.tagName === "INPUT" && fileInput.type === "file")) { - fileInput.style.position = "relative"; - const newFileInput = document.createElement("input"); - newFileInput.type = "file"; - newFileInput.style.position = "absolute"; - newFileInput.style.width = "100%"; - newFileInput.style.height = "100%"; - newFileInput.style.left = "0"; - newFileInput.style.top = "0"; - newFileInput.style.right = "0"; - newFileInput.style.bottom = "0"; - newFileInput.style.opacity = "0"; - fileInput.appendChild(newFileInput); - this.option.fileInput = newFileInput; - } - ["number", "width", "column", "begin", "end"].forEach((item) => { - this.errorHandle(typeof this.option[item] === "number", `The '${item}' is not a number`); - }); - this.option.number = clamp(number, 10, 1e3); - this.option.width = clamp(width, 10, 1e3); - this.option.column = clamp(column, 1, 1e3); + if (!destroyed.has(this)) + this.option = setupInput(this, option); return this; } static creatVideo() { @@ -124,16 +251,24 @@ class ArtplayerToolThumbnail extends Emitter { video.style.left = "-9999px"; video.muted = true; video.controls = true; - document.body.appendChild(video); + try { + document.body.appendChild(video); + } catch (error) { + if (video.parentNode) + video.parentNode.removeChild(video); + throw error; + } return video; } inputChange(event) { + if (destroyed.has(this)) + return; const file = this.option.fileInput.files[0]; this.loadVideo(file); event.target.value = ""; } loadVideo(file) { - if (file) { + if (file && !destroyed.has(this)) { const canPlayType = this.video.canPlayType(file.type); this.errorHandle( canPlayType === "maybe" || canPlayType === "probably", @@ -193,35 +328,10 @@ class ArtplayerToolThumbnail extends Emitter { }); } creatScreenshotDate() { - const { number, width, height, column, begin } = this.option; - const timeGap = this.duration / number; - const timePoints = [begin + timeGap]; - while (timePoints.length < number) { - const last = timePoints[timePoints.length - 1]; - timePoints.push(last + timeGap); - } - return timePoints.map((item, index) => ({ - time: item - timeGap / 2, - x: index % column * width, - y: Math.floor(index / column) * height - })); + return screenshotPoints(this.option, this.duration); } creatCanvas() { - const { number, width, height, column } = this.option; - const canvas = document.createElement("canvas"); - const context2D = canvas.getContext("2d"); - canvas.width = width * column; - canvas.height = Math.ceil(number / column) * height + 30; - context2D.fillStyle = "black"; - context2D.fillRect(0, 0, canvas.width, canvas.height); - context2D.font = "14px Georgia"; - context2D.fillStyle = "#fff"; - context2D.fillText( - `From: https://artplayer.org/, Number: ${number}, Width: ${width}, Height: ${height}, Column: ${column}`, - 10, - canvas.height - 11 - ); - return canvas; + return createSheet(this.option); } download() { this.errorHandle( @@ -229,13 +339,7 @@ class ArtplayerToolThumbnail extends Emitter { "Download does not seem to be ready, please create preview first" ); this.errorHandle(!this.processing, "There is currently a task in progress, please wait a moment..."); - const elink = document.createElement("a"); - const name = `${getFileName(this.file.name)}.png`; - elink.download = name; - elink.href = this.thumbnailUrl; - document.body.appendChild(elink); - elink.click(); - document.body.removeChild(elink); + const name = downloadSheet(this.file, this.thumbnailUrl); this.emit("download", name); return this; } @@ -246,17 +350,25 @@ class ArtplayerToolThumbnail extends Emitter { } } destroy() { - this.option.fileInput.removeEventListener("change", this.inputChange); - this.option.fileInput.removeEventListener("dragover", ArtplayerToolThumbnail.ondragover); - this.option.fileInput.removeEventListener("drop", ArtplayerToolThumbnail.ondrop); - document.body.removeChild(this.video); - if (this.videoUrl) { - URL.revokeObjectURL(this.videoUrl); + if (destroyed.has(this)) + return; + destroyed.add(this); + let failure; + for (const cleanup of [ + () => releaseInput(this), + () => this.video.parentNode?.removeChild(this.video), + () => this.videoUrl && URL.revokeObjectURL(this.videoUrl), + () => this.thumbnailUrl && URL.revokeObjectURL(this.thumbnailUrl), + () => this.emit("destroy") + ]) { + try { + cleanup(); + } catch (error) { + failure || (failure = error); + } } - if (this.thumbnailUrl) { - URL.revokeObjectURL(this.thumbnailUrl); - } - this.emit("destroy"); + if (failure) + throw failure; } } export { diff --git a/package.json b/package.json index ca5616571..9aeed4739 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", "typecheck": "node scripts/typecheck.mjs", - "test:unit": "node --test 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:unit": "node --test 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:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs", "test": "yarn test:node && yarn test:baseline", "test:browser": "playwright test", @@ -83,7 +83,7 @@ "generate:media:hls": "node scripts/generate-hls-fixture.mjs", "test:iframe": "node --test test/iframe-navigation.test.js test/iframe-boundaries.test.js test/iframe.test.js test/iframe-lifecycle.test.js refactor/scripts/iframe-contract.test.mjs refactor/scripts/iframe-types.test.mjs", "test:iframe-types-package": "node refactor/scripts/iframe-package-types.mjs", - "test:thumbnail": "node --test test/thumbnail.test.js refactor/scripts/thumbnail-contract.test.mjs" + "test:thumbnail": "node --test test/thumbnail-input.test.js test/thumbnail.test.js refactor/scripts/thumbnail-contract.test.mjs" }, "browserslist": "last 1 Chrome version", "devDependencies": { diff --git a/packages/artplayer-tool-thumbnail/ARCHITECTURE.md b/packages/artplayer-tool-thumbnail/ARCHITECTURE.md new file mode 100644 index 000000000..0cbfd121b --- /dev/null +++ b/packages/artplayer-tool-thumbnail/ARCHITECTURE.md @@ -0,0 +1,70 @@ +# Thumbnail tool maintenance map + +This package is being migrated under PKG-TOOL-THUMB-03. Input ownership and sheet +export are separated; extraction/source cancellation is still being implemented. +Strict TS and published declaration work belongs to PKG-TOOL-THUMB-04. Do not +infer complete migration or release readiness from this checkpoint. + +| File | Responsibility | +| --- | --- | +| src/index.js | Public class, historical method names, file/video events, current extraction loop and destruction entry | +| src/input.js | Option validation/clamps, file-input wrapper creation, listener registration/replacement and release | +| src/sheet.js | Midpoint grid, canvas/footer geometry, temporary download anchor | +| src/emitter.js | Existing on/once/emit/off semantics; provenance review remains in 04 | +| src/utils.js | Existing clamp, filename, sleep and serial-promise helpers | + +The entry delegates to input/sheet modules; neither module imports the entry. +Input records live in a private WeakMap, so callers replacing `option` cannot +lose ownership of generated inputs/listeners. Normal construction preserves the +existing instance-field order and bound inputChange/ondrop methods. DEFAULTS, +file/video event order, public method spelling and return values stay unchanged. + +Input setup validates options before changing DOM or committed options. A wrapper +receives one owned input; repeated setup with that wrapper reuses it. Replacement +installs the new listeners before releasing the old input. A failed new listener +installation rolls back its partial listeners/DOM. Explicit caller-provided file +inputs are never removed. Generated inputs are removed and the wrapper's previous +position is restored only if its current position still matches the tool's write. +The existing bound ondrop method is now registered correctly. + +Destroy is idempotent and attempts input, video, current URL and destroy-event +cleanup even when one step throws; the first cleanup error escapes afterward. +Setup/file-input/drop/load calls cannot recreate input/source resources after +destruction. The emitter is not globally cleared. This does **not yet** cancel +existing extraction timers or late Blob callbacks; pending work and replaced +source URLs remain tracked risks for the rest of 03. + +Sheet extraction preserves fractional coordinates, historical `creat*` names, +the 30-pixel footer and the filename algorithm. The temporary download anchor is +removed even if click throws. Default aspect-derived height and synchronous video +events currently match workspace 4.4.0; recovered 3.5.31 differs. See the frozen +[contract](../../refactor/baselines/thumbnail-contract.md) before changing defaults. + +## Validation and continuation + +Use Yarn and the repository scripts: + +```sh +yarn test:thumbnail +yarn build artplayer-tool-thumbnail +yarn test:browser test/browser/thumbnail-tool.spec.js test/browser/thumbnail-native.spec.js test/browser/thumbnail-input.spec.js +``` + +`test/thumbnail-input.test.js` contains candidate input/export regressions; set +ARTPLAYER_THUMBNAIL_BASELINE=1 to reproduce failures against frozen workspace +main. ARTPLAYER_THUMBNAIL_ARTIFACT selects an actual built artifact for Node and +browser candidate checks. `test/thumbnail.test.js` remains immutable-behavior +evidence against old implementations, including intentionally reproduced bugs. + +Browser records distinguish actual extraction from native Blob-unavailable +controls. Windows WebKit can load tested MP4 files over HTTP but returns error 4 +for native Blob URLs; this is not successful file extraction. Actual input/DOM +cleanup runs on all three engines, while extraction acceptance needs supported +Safari/WebKit evidence in 05. The independent tool example is +`docs/assets/example/tool.thumbnail.js`, not the external thumbnail plugin example. + +Continue 03 by introducing owned metadata/extraction jobs and source/thumbnail +URL cleanup. Add candidate failure/cancellation regressions and preserve old +tests; do not change default delay/height policy silently. Then migrate the final +module boundaries to strict TS in 04 and verify installed declarations/old paths. +See [task plan](../../refactor/plan.md) and [risk ledger](../../refactor/risks.json). diff --git a/packages/artplayer-tool-thumbnail/README.md b/packages/artplayer-tool-thumbnail/README.md index a6f227c0a..11e6cf924 100644 --- a/packages/artplayer-tool-thumbnail/README.md +++ b/packages/artplayer-tool-thumbnail/README.md @@ -2,6 +2,8 @@ Thumbnail tool for ArtPlayer +Implementation and migration notes: [ARCHITECTURE.md](./ARCHITECTURE.md). + ## Demo [https://artplayer.org](https://artplayer.org/?libs=./uncompiled/artplayer-tool-thumbnail/index.js&example=thumbnail) diff --git a/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.js b/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.js index e16cbeccd..32c840117 100644 --- a/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.js +++ b/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;n{this.errorHandle("number"===typeof this.option[t],`The '${t}' is not a number`)}),this.option.number=e(n,10,1e3),this.option.width=e(o,10,1e3),this.option.column=e(s,1,1e3),this}static creatVideo(){const t=document.createElement("video");return t.style.position="absolute",t.style.top="-9999px",t.style.left="-9999px",t.muted=!0,t.controls=!0,document.body.appendChild(t),t}inputChange(t){const e=this.option.fileInput.files[0];this.loadVideo(e),t.target.value=""}loadVideo(t){if(t){const e=this.video.canPlayType(t.type);this.errorHandle("maybe"===e||"probably"===e,`Playback of this file format is not supported: ${t.type}`);const i=URL.createObjectURL(t);this.videoUrl=i,this.file=t,this.emit("file",this.file),this.video.src=i,this.emit("video",this.video)}}start(){if(!this.video.duration)return(t=1e3,new Promise(e=>setTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const d=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(p=d,p.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var p}creatScreenshotDate(){const{number:t,width:e,height:i,column:n,begin:o}=this.option,s=this.duration/t,r=[o+s];for(;r.length({time:t-s/2,x:o%n*e,y:Math.floor(o/n)*i}))}creatCanvas(){const{number:t,width:e,height:i,column:n}=this.option,o=document.createElement("canvas"),s=o.getContext("2d");return o.width=e*n,o.height=Math.ceil(t/n)*i+30,s.fillStyle="black",s.fillRect(0,0,o.width,o.height),s.font="14px Georgia",s.fillStyle="#fff",s.fillText(`From: https://artplayer.org/, Number: ${t}, Width: ${e}, Height: ${i}, Column: ${n}`,10,o.height-11),o}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=document.createElement("a"),e=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(this.file.name)}.png`;return t.download=e,t.href=this.thumbnailUrl,document.body.appendChild(t),t.click(),document.body.removeChild(t),this.emit("download",e),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){this.option.fileInput.removeEventListener("change",this.inputChange),this.option.fileInput.removeEventListener("dragover",i.ondragover),this.option.fileInput.removeEventListener("drop",i.ondrop),document.body.removeChild(this.video),this.videoUrl&&URL.revokeObjectURL(this.videoUrl),this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.emit("destroy")}}return i}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;nsetTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const c=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(d=c,d.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var d}creatScreenshotDate(){return function(t,e){const{number:i,width:n,height:o,column:s,begin:r}=t,h=e/i,a=[r+h];for(;a.length({time:t-h/2,x:e%s*n,y:Math.floor(e/s)*o}))}(this.option,this.duration)}creatCanvas(){return function(t){const{number:e,width:i,height:n,column:o}=t,s=document.createElement("canvas"),r=s.getContext("2d");return s.width=i*o,s.height=Math.ceil(e/o)*n+30,r.fillStyle="black",r.fillRect(0,0,s.width,s.height),r.font="14px Georgia",r.fillStyle="#fff",r.fillText(`From: https://artplayer.org/, Number: ${e}, Width: ${i}, Height: ${n}, Column: ${o}`,10,s.height-11),s}(this.option)}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=function(t,e){const i=document.createElement("a"),n=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(t.name)}.png`;i.download=n,i.href=e;try{document.body.appendChild(i),i.click()}finally{i.parentNode&&i.parentNode.removeChild(i)}return n}(this.file,this.thumbnailUrl);return this.emit("download",t),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){if(r.has(this))return;let t;r.add(this);for(const i of[()=>s(this),()=>this.video.parentNode?.removeChild(this.video),()=>this.videoUrl&&URL.revokeObjectURL(this.videoUrl),()=>this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),()=>this.emit("destroy")])try{i()}catch(e){t||(t=e)}if(t)throw t}}return h}); diff --git a/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.legacy.js b/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.legacy.js index e16cbeccd..42395657e 100644 --- a/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.legacy.js +++ b/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;n{this.errorHandle("number"===typeof this.option[t],`The '${t}' is not a number`)}),this.option.number=e(n,10,1e3),this.option.width=e(o,10,1e3),this.option.column=e(s,1,1e3),this}static creatVideo(){const t=document.createElement("video");return t.style.position="absolute",t.style.top="-9999px",t.style.left="-9999px",t.muted=!0,t.controls=!0,document.body.appendChild(t),t}inputChange(t){const e=this.option.fileInput.files[0];this.loadVideo(e),t.target.value=""}loadVideo(t){if(t){const e=this.video.canPlayType(t.type);this.errorHandle("maybe"===e||"probably"===e,`Playback of this file format is not supported: ${t.type}`);const i=URL.createObjectURL(t);this.videoUrl=i,this.file=t,this.emit("file",this.file),this.video.src=i,this.emit("video",this.video)}}start(){if(!this.video.duration)return(t=1e3,new Promise(e=>setTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const d=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(p=d,p.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var p}creatScreenshotDate(){const{number:t,width:e,height:i,column:n,begin:o}=this.option,s=this.duration/t,r=[o+s];for(;r.length({time:t-s/2,x:o%n*e,y:Math.floor(o/n)*i}))}creatCanvas(){const{number:t,width:e,height:i,column:n}=this.option,o=document.createElement("canvas"),s=o.getContext("2d");return o.width=e*n,o.height=Math.ceil(t/n)*i+30,s.fillStyle="black",s.fillRect(0,0,o.width,o.height),s.font="14px Georgia",s.fillStyle="#fff",s.fillText(`From: https://artplayer.org/, Number: ${t}, Width: ${e}, Height: ${i}, Column: ${n}`,10,o.height-11),o}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=document.createElement("a"),e=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(this.file.name)}.png`;return t.download=e,t.href=this.thumbnailUrl,document.body.appendChild(t),t.click(),document.body.removeChild(t),this.emit("download",e),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){this.option.fileInput.removeEventListener("change",this.inputChange),this.option.fileInput.removeEventListener("dragover",i.ondragover),this.option.fileInput.removeEventListener("drop",i.ondrop),document.body.removeChild(this.video),this.videoUrl&&URL.revokeObjectURL(this.videoUrl),this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.emit("destroy")}}return i}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.ArtplayerToolThumbnail=e(),define(function(){return t.ArtplayerToolThumbnail})):(t="undefined"!==typeof globalThis?globalThis:t||self).ArtplayerToolThumbnail=e()}(this,function(){"use strict";class t{on(t,e,i){const n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this}once(t,e,i){const n=this;function o(...s){n.off(t,o),e.apply(i,s)}return o._=e,this.on(t,o,i)}emit(t,...e){const i=((this.e||(this.e={}))[t]||[]).slice();for(let n=0;nsetTimeout(e,t))).then(()=>this.start());var t;const{width:i,number:n,begin:o,end:s}=this.option,r=this.video.videoHeight/this.video.videoWidth*i;this.option.height=r,this.option.begin=e(o,0,this.video.duration),this.option.end=e(s||this.video.duration,o,this.video.duration),this.errorHandle(this.option.end>this.option.begin,"End time must be greater than the start time"),this.duration=this.option.end-this.option.begin,this.density=n/this.duration,this.errorHandle(this.file&&this.video,"Please select the video file first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment..."),this.errorHandle(this.density<=1,`The preview density cannot be greater than 1, but got ${this.density}`);const h=this.creatScreenshotDate(),a=this.creatCanvas(),l=a.getContext("2d");this.emit("canvas",a);const c=h.map((t,e)=>()=>new Promise(o=>{this.video.oncanplay=()=>{l.drawImage(this.video,t.x,t.y,i,r),a.toBlob(t=>{this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),this.thumbnailUrl=URL.createObjectURL(t),this.emit("update",this.thumbnailUrl,(e+1)/n),this.video.oncanplay=null,o()})},this.video.currentTime=t.time}));return this.processing=!0,(d=c,d.reduce((t,e)=>t.then(e),Promise.resolve())).then(()=>{this.processing=!1,this.emit("done")}).catch(t=>{throw this.processing=!1,this.emit("error",t.message),t});var d}creatScreenshotDate(){return function(t,e){const{number:i,width:n,height:o,column:s,begin:r}=t,h=e/i,a=[r+h];for(;a.length({time:t-h/2,x:e%s*n,y:Math.floor(e/s)*o}))}(this.option,this.duration)}creatCanvas(){return function(t){const{number:e,width:i,height:n,column:o}=t,s=document.createElement("canvas"),r=s.getContext("2d");return s.width=i*o,s.height=Math.ceil(e/o)*n+30,r.fillStyle="black",r.fillRect(0,0,s.width,s.height),r.font="14px Georgia",r.fillStyle="#fff",r.fillText(`From: https://artplayer.org/, Number: ${e}, Width: ${i}, Height: ${n}, Column: ${o}`,10,s.height-11),s}(this.option)}download(){this.errorHandle(this.file&&this.thumbnailUrl,"Download does not seem to be ready, please create preview first"),this.errorHandle(!this.processing,"There is currently a task in progress, please wait a moment...");const t=function(t,e){const i=document.createElement("a"),n=`${function(t){const e=t.split(".");return e.pop(),e.join(".")}(t.name)}.png`;i.download=n,i.href=e;try{document.body.appendChild(i),i.click()}finally{i.parentNode&&i.parentNode.removeChild(i)}return n}(this.file,this.thumbnailUrl);return this.emit("download",t),this}errorHandle(t,e){if(!t)throw this.emit("error",e),new Error(e)}destroy(){if(r.has(this))return;let t;r.add(this);for(const i of[()=>s(this),()=>{var t;return null==(t=this.video.parentNode)?void 0:t.removeChild(this.video)},()=>this.videoUrl&&URL.revokeObjectURL(this.videoUrl),()=>this.thumbnailUrl&&URL.revokeObjectURL(this.thumbnailUrl),()=>this.emit("destroy")])try{i()}catch(e){t||(t=e)}if(t)throw t}}return h}); diff --git a/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.mjs b/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.mjs index f0eab6e03..4d0159c08 100644 --- a/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.mjs +++ b/packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.mjs @@ -58,19 +58,166 @@ function getFileName(name) { function clamp(num, a, b) { return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); } +const inputs = /* @__PURE__ */ new WeakMap(); +function release(record) { + let failure; + for (const [name, callback] of record.listeners.splice(0)) { + try { + record.input.removeEventListener(name, callback); + } catch (error) { + failure || (failure = error); + } + } + if (record.wrapper) { + try { + if (record.input.parentNode) + record.input.parentNode.removeChild(record.input); + } catch (error) { + failure || (failure = error); + } + if (record.wrapper.style.position === "relative") + record.wrapper.style.position = record.position; + } + if (failure) + throw failure; +} +function connect(record, callbacks) { + try { + for (const [name, callback] of callbacks) { + record.listeners.push([name, callback]); + record.input.addEventListener(name, callback); + } + } catch (error) { + try { + release(record); + } catch { + } + throw error; + } +} +function setupInput(tool, patch) { + const option = Object.assign({}, tool.option, patch); + const target = option.fileInput; + tool.errorHandle(target instanceof Element, "The 'fileInput' is not a Element"); + for (const name of ["number", "width", "column", "begin", "end"]) + tool.errorHandle(typeof option[name] === "number", `The '${name}' is not a number`); + option.number = clamp(option.number, 10, 1e3); + option.width = clamp(option.width, 10, 1e3); + option.column = clamp(option.column, 1, 1e3); + const previous = inputs.get(tool); + if (previous && (target === previous.input || target === previous.wrapper)) { + option.fileInput = previous.input; + return option; + } + const record = { input: target, wrapper: null, position: "", listeners: [], callbacks: previous?.callbacks || null }; + try { + if (!(target.tagName === "INPUT" && target.type === "file")) { + record.wrapper = target; + record.position = target.style.position; + record.input = document.createElement("input"); + record.input.type = "file"; + Object.assign(record.input.style, { position: "absolute", width: "100%", height: "100%", left: "0", top: "0", right: "0", bottom: "0", opacity: "0" }); + target.style.position = "relative"; + target.appendChild(record.input); + } + if (record.callbacks) + connect(record, record.callbacks); + } catch (error) { + try { + release(record); + } catch { + } + throw error; + } + option.fileInput = record.input; + inputs.set(tool, record); + tool.option = option; + if (previous) + release(previous); + return option; +} +function connectInput(tool, dragover) { + const record = inputs.get(tool); + record.callbacks = [["change", tool.inputChange], ["dragover", dragover], ["drop", tool.ondrop]]; + connect(record, record.callbacks); +} +function releaseInput(tool) { + const record = inputs.get(tool); + if (!record) + return; + inputs.delete(tool); + release(record); +} +function screenshotPoints(option, duration) { + const { number, width, height, column, begin } = option; + const timeGap = duration / number; + const timePoints = [begin + timeGap]; + while (timePoints.length < number) { + const last = timePoints[timePoints.length - 1]; + timePoints.push(last + timeGap); + } + return timePoints.map((item, index) => ({ + time: item - timeGap / 2, + x: index % column * width, + y: Math.floor(index / column) * height + })); +} +function createSheet(option) { + const { number, width, height, column } = option; + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + canvas.width = width * column; + canvas.height = Math.ceil(number / column) * height + 30; + context.fillStyle = "black"; + context.fillRect(0, 0, canvas.width, canvas.height); + context.font = "14px Georgia"; + context.fillStyle = "#fff"; + context.fillText( + `From: https://artplayer.org/, Number: ${number}, Width: ${width}, Height: ${height}, Column: ${column}`, + 10, + canvas.height - 11 + ); + return canvas; +} +function downloadSheet(file, url) { + const link = document.createElement("a"); + const name = `${getFileName(file.name)}.png`; + link.download = name; + link.href = url; + try { + document.body.appendChild(link); + link.click(); + } finally { + if (link.parentNode) + link.parentNode.removeChild(link); + } + return name; +} +const destroyed = /* @__PURE__ */ new WeakSet(); class ArtplayerToolThumbnail extends Emitter { constructor(option = {}) { super(); this.processing = false; this.option = {}; - this.setup(Object.assign({}, ArtplayerToolThumbnail.DEFAULTS, option)); - this.video = ArtplayerToolThumbnail.creatVideo(); - this.duration = 0; - this.inputChange = this.inputChange.bind(this); - this.ondrop = this.ondrop.bind(this); - this.option.fileInput.addEventListener("change", this.inputChange); - this.option.fileInput.addEventListener("dragover", ArtplayerToolThumbnail.ondragover); - this.option.fileInput.addEventListener("drop", ArtplayerToolThumbnail.ondrop); + try { + this.setup(Object.assign({}, ArtplayerToolThumbnail.DEFAULTS, option)); + this.video = ArtplayerToolThumbnail.creatVideo(); + this.duration = 0; + this.inputChange = this.inputChange.bind(this); + this.ondrop = this.ondrop.bind(this); + connectInput(this, ArtplayerToolThumbnail.ondragover); + } catch (error) { + try { + releaseInput(this); + } catch { + } + try { + if (this.video?.parentNode) + this.video.parentNode.removeChild(this.video); + } catch { + } + throw error; + } } static get DEFAULTS() { return { @@ -86,35 +233,15 @@ class ArtplayerToolThumbnail extends Emitter { event.preventDefault(); } ondrop(event) { + if (destroyed.has(this)) + return; event.preventDefault(); const file = event.dataTransfer.files[0]; this.loadVideo(file); } setup(option = {}) { - this.option = Object.assign({}, this.option, option); - const { fileInput, number, width, column } = this.option; - this.errorHandle(fileInput instanceof Element, "The 'fileInput' is not a Element"); - if (!(fileInput.tagName === "INPUT" && fileInput.type === "file")) { - fileInput.style.position = "relative"; - const newFileInput = document.createElement("input"); - newFileInput.type = "file"; - newFileInput.style.position = "absolute"; - newFileInput.style.width = "100%"; - newFileInput.style.height = "100%"; - newFileInput.style.left = "0"; - newFileInput.style.top = "0"; - newFileInput.style.right = "0"; - newFileInput.style.bottom = "0"; - newFileInput.style.opacity = "0"; - fileInput.appendChild(newFileInput); - this.option.fileInput = newFileInput; - } - ["number", "width", "column", "begin", "end"].forEach((item) => { - this.errorHandle(typeof this.option[item] === "number", `The '${item}' is not a number`); - }); - this.option.number = clamp(number, 10, 1e3); - this.option.width = clamp(width, 10, 1e3); - this.option.column = clamp(column, 1, 1e3); + if (!destroyed.has(this)) + this.option = setupInput(this, option); return this; } static creatVideo() { @@ -124,16 +251,24 @@ class ArtplayerToolThumbnail extends Emitter { video.style.left = "-9999px"; video.muted = true; video.controls = true; - document.body.appendChild(video); + try { + document.body.appendChild(video); + } catch (error) { + if (video.parentNode) + video.parentNode.removeChild(video); + throw error; + } return video; } inputChange(event) { + if (destroyed.has(this)) + return; const file = this.option.fileInput.files[0]; this.loadVideo(file); event.target.value = ""; } loadVideo(file) { - if (file) { + if (file && !destroyed.has(this)) { const canPlayType = this.video.canPlayType(file.type); this.errorHandle( canPlayType === "maybe" || canPlayType === "probably", @@ -193,35 +328,10 @@ class ArtplayerToolThumbnail extends Emitter { }); } creatScreenshotDate() { - const { number, width, height, column, begin } = this.option; - const timeGap = this.duration / number; - const timePoints = [begin + timeGap]; - while (timePoints.length < number) { - const last = timePoints[timePoints.length - 1]; - timePoints.push(last + timeGap); - } - return timePoints.map((item, index) => ({ - time: item - timeGap / 2, - x: index % column * width, - y: Math.floor(index / column) * height - })); + return screenshotPoints(this.option, this.duration); } creatCanvas() { - const { number, width, height, column } = this.option; - const canvas = document.createElement("canvas"); - const context2D = canvas.getContext("2d"); - canvas.width = width * column; - canvas.height = Math.ceil(number / column) * height + 30; - context2D.fillStyle = "black"; - context2D.fillRect(0, 0, canvas.width, canvas.height); - context2D.font = "14px Georgia"; - context2D.fillStyle = "#fff"; - context2D.fillText( - `From: https://artplayer.org/, Number: ${number}, Width: ${width}, Height: ${height}, Column: ${column}`, - 10, - canvas.height - 11 - ); - return canvas; + return createSheet(this.option); } download() { this.errorHandle( @@ -229,13 +339,7 @@ class ArtplayerToolThumbnail extends Emitter { "Download does not seem to be ready, please create preview first" ); this.errorHandle(!this.processing, "There is currently a task in progress, please wait a moment..."); - const elink = document.createElement("a"); - const name = `${getFileName(this.file.name)}.png`; - elink.download = name; - elink.href = this.thumbnailUrl; - document.body.appendChild(elink); - elink.click(); - document.body.removeChild(elink); + const name = downloadSheet(this.file, this.thumbnailUrl); this.emit("download", name); return this; } @@ -246,17 +350,25 @@ class ArtplayerToolThumbnail extends Emitter { } } destroy() { - this.option.fileInput.removeEventListener("change", this.inputChange); - this.option.fileInput.removeEventListener("dragover", ArtplayerToolThumbnail.ondragover); - this.option.fileInput.removeEventListener("drop", ArtplayerToolThumbnail.ondrop); - document.body.removeChild(this.video); - if (this.videoUrl) { - URL.revokeObjectURL(this.videoUrl); + if (destroyed.has(this)) + return; + destroyed.add(this); + let failure; + for (const cleanup of [ + () => releaseInput(this), + () => this.video.parentNode?.removeChild(this.video), + () => this.videoUrl && URL.revokeObjectURL(this.videoUrl), + () => this.thumbnailUrl && URL.revokeObjectURL(this.thumbnailUrl), + () => this.emit("destroy") + ]) { + try { + cleanup(); + } catch (error) { + failure || (failure = error); + } } - if (this.thumbnailUrl) { - URL.revokeObjectURL(this.thumbnailUrl); - } - this.emit("destroy"); + if (failure) + throw failure; } } export { diff --git a/packages/artplayer-tool-thumbnail/src/index.js b/packages/artplayer-tool-thumbnail/src/index.js index 2715bc75e..63f424b21 100644 --- a/packages/artplayer-tool-thumbnail/src/index.js +++ b/packages/artplayer-tool-thumbnail/src/index.js @@ -1,19 +1,35 @@ import Emitter from './emitter' -import { clamp, getFileName, runPromisesInSeries, sleep } from './utils' +import { connectInput, releaseInput, setupInput } from './input' +import { createSheet, downloadSheet, screenshotPoints } from './sheet' +import { clamp, runPromisesInSeries, sleep } from './utils' + +const destroyed = new WeakSet() export default class ArtplayerToolThumbnail extends Emitter { constructor(option = {}) { super() this.processing = false this.option = {} - this.setup(Object.assign({}, ArtplayerToolThumbnail.DEFAULTS, option)) - this.video = ArtplayerToolThumbnail.creatVideo() - this.duration = 0 - this.inputChange = this.inputChange.bind(this) - this.ondrop = this.ondrop.bind(this) - this.option.fileInput.addEventListener('change', this.inputChange) - this.option.fileInput.addEventListener('dragover', ArtplayerToolThumbnail.ondragover) - this.option.fileInput.addEventListener('drop', ArtplayerToolThumbnail.ondrop) + try { + this.setup(Object.assign({}, ArtplayerToolThumbnail.DEFAULTS, option)) + this.video = ArtplayerToolThumbnail.creatVideo() + this.duration = 0 + this.inputChange = this.inputChange.bind(this) + this.ondrop = this.ondrop.bind(this) + connectInput(this, ArtplayerToolThumbnail.ondragover) + } + catch (error) { + try { + releaseInput(this) + } + catch {} + try { + if (this.video?.parentNode) + this.video.parentNode.removeChild(this.video) + } + catch {} + throw error + } } static get DEFAULTS() { @@ -32,40 +48,16 @@ export default class ArtplayerToolThumbnail extends Emitter { } ondrop(event) { + if (destroyed.has(this)) + return event.preventDefault() const file = event.dataTransfer.files[0] this.loadVideo(file) } setup(option = {}) { - this.option = Object.assign({}, this.option, option) - const { fileInput, number, width, column } = this.option - - this.errorHandle(fileInput instanceof Element, 'The \'fileInput\' is not a Element') - - if (!(fileInput.tagName === 'INPUT' && fileInput.type === 'file')) { - fileInput.style.position = 'relative' - const newFileInput = document.createElement('input') - newFileInput.type = 'file' - newFileInput.style.position = 'absolute' - newFileInput.style.width = '100%' - newFileInput.style.height = '100%' - newFileInput.style.left = '0' - newFileInput.style.top = '0' - newFileInput.style.right = '0' - newFileInput.style.bottom = '0' - newFileInput.style.opacity = '0' - fileInput.appendChild(newFileInput) - this.option.fileInput = newFileInput - } - - ['number', 'width', 'column', 'begin', 'end'].forEach((item) => { - this.errorHandle(typeof this.option[item] === 'number', `The '${item}' is not a number`) - }) - - this.option.number = clamp(number, 10, 1000) - this.option.width = clamp(width, 10, 1000) - this.option.column = clamp(column, 1, 1000) + if (!destroyed.has(this)) + this.option = setupInput(this, option) return this } @@ -76,18 +68,27 @@ export default class ArtplayerToolThumbnail extends Emitter { video.style.left = '-9999px' video.muted = true video.controls = true - document.body.appendChild(video) + try { + document.body.appendChild(video) + } + catch (error) { + if (video.parentNode) + video.parentNode.removeChild(video) + throw error + } return video } inputChange(event) { + if (destroyed.has(this)) + return const file = this.option.fileInput.files[0] this.loadVideo(file) event.target.value = '' } loadVideo(file) { - if (file) { + if (file && !destroyed.has(this)) { const canPlayType = this.video.canPlayType(file.type) this.errorHandle( canPlayType === 'maybe' || canPlayType === 'probably', @@ -151,36 +152,11 @@ export default class ArtplayerToolThumbnail extends Emitter { } creatScreenshotDate() { - const { number, width, height, column, begin } = this.option - const timeGap = this.duration / number - const timePoints = [begin + timeGap] - while (timePoints.length < number) { - const last = timePoints[timePoints.length - 1] - timePoints.push(last + timeGap) - } - return timePoints.map((item, index) => ({ - time: item - timeGap / 2, - x: (index % column) * width, - y: Math.floor(index / column) * height, - })) + return screenshotPoints(this.option, this.duration) } creatCanvas() { - const { number, width, height, column } = this.option - const canvas = document.createElement('canvas') - const context2D = canvas.getContext('2d') - canvas.width = width * column - canvas.height = Math.ceil(number / column) * height + 30 - context2D.fillStyle = 'black' - context2D.fillRect(0, 0, canvas.width, canvas.height) - context2D.font = '14px Georgia' - context2D.fillStyle = '#fff' - context2D.fillText( - `From: https://artplayer.org/, Number: ${number}, Width: ${width}, Height: ${height}, Column: ${column}`, - 10, - canvas.height - 11, - ) - return canvas + return createSheet(this.option) } download() { @@ -189,13 +165,7 @@ export default class ArtplayerToolThumbnail extends Emitter { 'Download does not seem to be ready, please create preview first', ) this.errorHandle(!this.processing, 'There is currently a task in progress, please wait a moment...') - const elink = document.createElement('a') - const name = `${getFileName(this.file.name)}.png` - elink.download = name - elink.href = this.thumbnailUrl - document.body.appendChild(elink) - elink.click() - document.body.removeChild(elink) + const name = downloadSheet(this.file, this.thumbnailUrl) this.emit('download', name) return this } @@ -208,16 +178,23 @@ export default class ArtplayerToolThumbnail extends Emitter { } destroy() { - this.option.fileInput.removeEventListener('change', this.inputChange) - this.option.fileInput.removeEventListener('dragover', ArtplayerToolThumbnail.ondragover) - this.option.fileInput.removeEventListener('drop', ArtplayerToolThumbnail.ondrop) - document.body.removeChild(this.video) - if (this.videoUrl) { - URL.revokeObjectURL(this.videoUrl) + if (destroyed.has(this)) + return + destroyed.add(this) + let failure + for (const cleanup of [ + () => releaseInput(this), + () => this.video.parentNode?.removeChild(this.video), + () => this.videoUrl && URL.revokeObjectURL(this.videoUrl), + () => this.thumbnailUrl && URL.revokeObjectURL(this.thumbnailUrl), + () => this.emit('destroy'), + ]) { + try { + cleanup() + } + catch (error) { failure ||= error } } - if (this.thumbnailUrl) { - URL.revokeObjectURL(this.thumbnailUrl) - } - this.emit('destroy') + if (failure) + throw failure } } diff --git a/packages/artplayer-tool-thumbnail/src/input.js b/packages/artplayer-tool-thumbnail/src/input.js new file mode 100644 index 000000000..f209a9ad4 --- /dev/null +++ b/packages/artplayer-tool-thumbnail/src/input.js @@ -0,0 +1,102 @@ +import { clamp } from './utils' + +const inputs = new WeakMap() + +function release(record) { + let failure + for (const [name, callback] of record.listeners.splice(0)) { + try { + record.input.removeEventListener(name, callback) + } + catch (error) { + failure ||= error + } + } + if (record.wrapper) { + try { + if (record.input.parentNode) + record.input.parentNode.removeChild(record.input) + } + catch (error) { + failure ||= error + } + if (record.wrapper.style.position === 'relative') + record.wrapper.style.position = record.position + } + if (failure) + throw failure +} + +function connect(record, callbacks) { + try { + for (const [name, callback] of callbacks) { + record.listeners.push([name, callback]) + record.input.addEventListener(name, callback) + } + } + catch (error) { + try { + release(record) + } + catch {} + throw error + } +} + +export function setupInput(tool, patch) { + const option = Object.assign({}, tool.option, patch) + const target = option.fileInput + tool.errorHandle(target instanceof Element, 'The \'fileInput\' is not a Element') + for (const name of ['number', 'width', 'column', 'begin', 'end']) + tool.errorHandle(typeof option[name] === 'number', `The '${name}' is not a number`) + option.number = clamp(option.number, 10, 1000) + option.width = clamp(option.width, 10, 1000) + option.column = clamp(option.column, 1, 1000) + + const previous = inputs.get(tool) + if (previous && (target === previous.input || target === previous.wrapper)) { + option.fileInput = previous.input + return option + } + const record = { input: target, wrapper: null, position: '', listeners: [], callbacks: previous?.callbacks || null } + try { + if (!(target.tagName === 'INPUT' && target.type === 'file')) { + record.wrapper = target + record.position = target.style.position + record.input = document.createElement('input') + record.input.type = 'file' + Object.assign(record.input.style, { position: 'absolute', width: '100%', height: '100%', left: '0', top: '0', right: '0', bottom: '0', opacity: '0' }) + target.style.position = 'relative' + target.appendChild(record.input) + } + if (record.callbacks) + connect(record, record.callbacks) + } + catch (error) { + try { + release(record) + } + catch {} + throw error + } + option.fileInput = record.input + inputs.set(tool, record) + tool.option = option + if (previous) + release(previous) + return option +} + +export function connectInput(tool, dragover) { + const record = inputs.get(tool) + record.callbacks = [['change', tool.inputChange], ['dragover', dragover], ['drop', tool.ondrop]] + connect(record, record.callbacks) +} + +export function releaseInput(tool) { + const record = inputs.get(tool) + if (!record) + return + inputs.delete(tool) + release(record) +} diff --git a/packages/artplayer-tool-thumbnail/src/sheet.js b/packages/artplayer-tool-thumbnail/src/sheet.js new file mode 100644 index 000000000..5ffcd2ad5 --- /dev/null +++ b/packages/artplayer-tool-thumbnail/src/sheet.js @@ -0,0 +1,50 @@ +import { getFileName } from './utils' + +export function screenshotPoints(option, duration) { + const { number, width, height, column, begin } = option + const timeGap = duration / number + const timePoints = [begin + timeGap] + while (timePoints.length < number) { + const last = timePoints[timePoints.length - 1] + timePoints.push(last + timeGap) + } + return timePoints.map((item, index) => ({ + time: item - timeGap / 2, + x: (index % column) * width, + y: Math.floor(index / column) * height, + })) +} + +export function createSheet(option) { + const { number, width, height, column } = option + const canvas = document.createElement('canvas') + const context = canvas.getContext('2d') + canvas.width = width * column + canvas.height = Math.ceil(number / column) * height + 30 + context.fillStyle = 'black' + context.fillRect(0, 0, canvas.width, canvas.height) + context.font = '14px Georgia' + context.fillStyle = '#fff' + context.fillText( + `From: https://artplayer.org/, Number: ${number}, Width: ${width}, Height: ${height}, Column: ${column}`, + 10, + canvas.height - 11, + ) + return canvas +} + +export function downloadSheet(file, url) { + const link = document.createElement('a') + const name = `${getFileName(file.name)}.png` + link.download = name + link.href = url + try { + document.body.appendChild(link) + link.click() + } + finally { + if (link.parentNode) + link.parentNode.removeChild(link) + } + return name +} diff --git a/refactor/baselines/thumbnail-input-checkpoint.json b/refactor/baselines/thumbnail-input-checkpoint.json new file mode 100644 index 000000000..74fac0a11 --- /dev/null +++ b/refactor/baselines/thumbnail-input-checkpoint.json @@ -0,0 +1,12667 @@ +{ + "schemaVersion": 1, + "task": "PKG-TOOL-THUMB-03", + "taskStatus": "doing", + "verifiedAt": "2026-09-12T19:51:02.085Z", + "startedFrom": "1cb7779192cf552c0dfabcbb6de4f26b39e33045", + "nodeVersion": "v24.21.0", + "node": { + "frozenBefore": { + "passed": 2, + "failed": 12 + }, + "source": { + "passed": 14, + "failed": 0 + }, + "main": { + "passed": 14, + "failed": 0 + }, + "legacy": { + "passed": 14, + "failed": 0 + } + }, + "ci": { + "total": 1620, + "unit": 1415, + "engineering": 14, + "baseline": 191, + "productionTs": 330, + "imports": 3 + }, + "browser": { + "total": 162, + "retries": 0, + "skips": 0, + "runs": [ + { + "variant": "source", + "counts": { + "candidate-native-input": 3, + "native-media-control": 3, + "blob-unavailable-control": 16, + "actual-tool-scenario": 32 + }, + "cases": [ + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "chromium", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 286, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "firefox", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 1761, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "webkit", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 777, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "chromium", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 243, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.046009, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.046009, + "width": 640 + } + ] + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "firefox", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 2044, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 3, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.045986, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.045986, + "width": 640 + } + ] + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "webkit", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 2096, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 3, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 2, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 2, + "error": 0, + "duration": 90.094, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + } + ] + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 8132, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 150, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 30, + "mime": "image/png", + "bytes": 26427, + "nonBlack": 2400, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/31d9a61b-0835-4a8e-ae13-007c2745be10", + "second": "blob:http://127.0.0.1:8084/6305d980-998d-4c9f-80d9-e08c2e1d6c83", + "created": [ + "blob:http://127.0.0.1:8084/58bebc17-f68b-4813-8b75-4578a4161fc7", + "blob:http://127.0.0.1:8084/438d2cd4-2de7-4275-8269-3ec811b659b5", + "blob:http://127.0.0.1:8084/31b3b471-90f8-44f3-8045-860a433a6e03", + "blob:http://127.0.0.1:8084/f3a1ed15-c00e-4c48-841d-dc1762ada599", + "blob:http://127.0.0.1:8084/e60c1215-6b9e-4922-9836-b84ef65b51ce", + "blob:http://127.0.0.1:8084/3bb6c782-ae03-4377-b8af-fd1b16f6a65a", + "blob:http://127.0.0.1:8084/9d27591c-e050-46b9-9179-481054cb815e", + "blob:http://127.0.0.1:8084/6d5cad6d-a64a-4823-a75f-f0721badde15", + "blob:http://127.0.0.1:8084/1fc08c4b-b18e-4b75-92a6-b2992683f84a", + "blob:http://127.0.0.1:8084/56eaf88d-6b72-41db-875b-ee55e5feac25", + "blob:http://127.0.0.1:8084/31d9a61b-0835-4a8e-ae13-007c2745be10", + "blob:http://127.0.0.1:8084/a3fc6e6a-1734-44f1-b5ca-c3dd84daef0a", + "blob:http://127.0.0.1:8084/0e3126bb-6790-4d44-90d3-37b7e538956f", + "blob:http://127.0.0.1:8084/8a8982be-8e5c-4d5c-bbd5-889f4a299e94", + "blob:http://127.0.0.1:8084/ec45a06b-9a1e-4399-b6da-e339cc46c568", + "blob:http://127.0.0.1:8084/8e1d8528-cccd-4a42-82a1-46ce13084274", + "blob:http://127.0.0.1:8084/ffe463be-3cff-4560-aa40-8212e98f4659", + "blob:http://127.0.0.1:8084/ae875276-4f91-4b3b-88a5-86c1a27fcf68", + "blob:http://127.0.0.1:8084/a9ca302b-264d-45df-90df-77b1ec506b0c", + "blob:http://127.0.0.1:8084/1816b577-3da6-44fa-b87f-0edea2b1e576", + "blob:http://127.0.0.1:8084/6305d980-998d-4c9f-80d9-e08c2e1d6c83" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/438d2cd4-2de7-4275-8269-3ec811b659b5", + "blob:http://127.0.0.1:8084/31b3b471-90f8-44f3-8045-860a433a6e03", + "blob:http://127.0.0.1:8084/f3a1ed15-c00e-4c48-841d-dc1762ada599", + "blob:http://127.0.0.1:8084/e60c1215-6b9e-4922-9836-b84ef65b51ce", + "blob:http://127.0.0.1:8084/3bb6c782-ae03-4377-b8af-fd1b16f6a65a", + "blob:http://127.0.0.1:8084/9d27591c-e050-46b9-9179-481054cb815e", + "blob:http://127.0.0.1:8084/6d5cad6d-a64a-4823-a75f-f0721badde15", + "blob:http://127.0.0.1:8084/1fc08c4b-b18e-4b75-92a6-b2992683f84a", + "blob:http://127.0.0.1:8084/56eaf88d-6b72-41db-875b-ee55e5feac25", + "blob:http://127.0.0.1:8084/31d9a61b-0835-4a8e-ae13-007c2745be10", + "blob:http://127.0.0.1:8084/a3fc6e6a-1734-44f1-b5ca-c3dd84daef0a", + "blob:http://127.0.0.1:8084/0e3126bb-6790-4d44-90d3-37b7e538956f", + "blob:http://127.0.0.1:8084/8a8982be-8e5c-4d5c-bbd5-889f4a299e94", + "blob:http://127.0.0.1:8084/ec45a06b-9a1e-4399-b6da-e339cc46c568", + "blob:http://127.0.0.1:8084/8e1d8528-cccd-4a42-82a1-46ce13084274", + "blob:http://127.0.0.1:8084/ffe463be-3cff-4560-aa40-8212e98f4659", + "blob:http://127.0.0.1:8084/ae875276-4f91-4b3b-88a5-86c1a27fcf68", + "blob:http://127.0.0.1:8084/a9ca302b-264d-45df-90df-77b1ec506b0c", + "blob:http://127.0.0.1:8084/1816b577-3da6-44fa-b87f-0edea2b1e576", + "blob:http://127.0.0.1:8084/58bebc17-f68b-4813-8b75-4578a4161fc7", + "blob:http://127.0.0.1:8084/6305d980-998d-4c9f-80d9-e08c2e1d6c83" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 204, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 251, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/e7be0844-581e-4fe5-9164-a6fd87e3229a" + }, + "result": { + "value": "C:\\fakepath\\thumbnail-pattern.mp4", + "created": [ + "blob:http://127.0.0.1:8084/e7be0844-581e-4fe5-9164-a6fd87e3229a", + "blob:http://127.0.0.1:8084/61f8e173-ef96-4aeb-b26d-168e8f05d4c8" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/61f8e173-ef96-4aeb-b26d-168e8f05d4c8" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 626, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/5c05f1c5-7aad-4b1d-a2d9-5413b6bf468e", + "blob:http://127.0.0.1:8084/b550e1d3-bcfe-4133-bd53-1dd7ce7e88a5" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/5c05f1c5-7aad-4b1d-a2d9-5413b6bf468e" + ], + "pendingState": "pending", + "events": [ + "file", + "canvas", + "video", + "destroy", + "update" + ], + "connected": false, + "bytes": 7540 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 8481, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 150, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 30, + "mime": "image/png", + "bytes": 20020, + "nonBlack": 2400, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/1adb16eb-77c4-4344-932f-e0a3eaadebd7", + "second": "blob:http://127.0.0.1:8084/cad56601-f6c5-46b5-b212-d368b81839d9", + "created": [ + "blob:http://127.0.0.1:8084/2a5e9d5a-24f9-4ad3-af06-3c2ed5c976b4", + "blob:http://127.0.0.1:8084/fc8d5ee9-e98c-48a6-8952-91935330fce4", + "blob:http://127.0.0.1:8084/0bae1aa1-6166-49ba-b8dc-8b204750984c", + "blob:http://127.0.0.1:8084/7cd1991f-d49c-4bd1-b7cd-4c3e54450c57", + "blob:http://127.0.0.1:8084/fc04e99e-938d-40c0-855f-ebc2626cc963", + "blob:http://127.0.0.1:8084/f5439f4a-e4c8-4b6d-962b-d605dc0bd09e", + "blob:http://127.0.0.1:8084/fe84788b-29d7-4243-8ce0-f817cc80586a", + "blob:http://127.0.0.1:8084/ddf7ec3a-5518-460d-99e9-05366e21bd99", + "blob:http://127.0.0.1:8084/0950abf0-16fd-4bf0-8615-9a68cb599e81", + "blob:http://127.0.0.1:8084/bd6f591e-5f48-4896-be93-7420cb09dbdc", + "blob:http://127.0.0.1:8084/1adb16eb-77c4-4344-932f-e0a3eaadebd7", + "blob:http://127.0.0.1:8084/f9f9e74a-05dc-40f1-8eb8-2835e58a20f9", + "blob:http://127.0.0.1:8084/d16af4b0-2884-4349-8293-d8042ebb8332", + "blob:http://127.0.0.1:8084/57749a48-f4f1-48c0-90fc-35cd196963c4", + "blob:http://127.0.0.1:8084/c01d44a7-9e1c-462f-882d-4530b42f3e71", + "blob:http://127.0.0.1:8084/404d7865-7316-42d4-ad1f-82ddab4a6fc1", + "blob:http://127.0.0.1:8084/c0ab3fa3-cb94-4faa-95ee-10a0a409a2bb", + "blob:http://127.0.0.1:8084/655ef861-33f2-469e-a456-42b0e10ef121", + "blob:http://127.0.0.1:8084/7042f1c3-20fd-408b-8550-60abb6b2044d", + "blob:http://127.0.0.1:8084/adbf7c6f-0470-43df-bea0-754920e57201", + "blob:http://127.0.0.1:8084/cad56601-f6c5-46b5-b212-d368b81839d9" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/fc8d5ee9-e98c-48a6-8952-91935330fce4", + "blob:http://127.0.0.1:8084/0bae1aa1-6166-49ba-b8dc-8b204750984c", + "blob:http://127.0.0.1:8084/7cd1991f-d49c-4bd1-b7cd-4c3e54450c57", + "blob:http://127.0.0.1:8084/fc04e99e-938d-40c0-855f-ebc2626cc963", + "blob:http://127.0.0.1:8084/f5439f4a-e4c8-4b6d-962b-d605dc0bd09e", + "blob:http://127.0.0.1:8084/fe84788b-29d7-4243-8ce0-f817cc80586a", + "blob:http://127.0.0.1:8084/ddf7ec3a-5518-460d-99e9-05366e21bd99", + "blob:http://127.0.0.1:8084/0950abf0-16fd-4bf0-8615-9a68cb599e81", + "blob:http://127.0.0.1:8084/bd6f591e-5f48-4896-be93-7420cb09dbdc", + "blob:http://127.0.0.1:8084/1adb16eb-77c4-4344-932f-e0a3eaadebd7", + "blob:http://127.0.0.1:8084/f9f9e74a-05dc-40f1-8eb8-2835e58a20f9", + "blob:http://127.0.0.1:8084/d16af4b0-2884-4349-8293-d8042ebb8332", + "blob:http://127.0.0.1:8084/57749a48-f4f1-48c0-90fc-35cd196963c4", + "blob:http://127.0.0.1:8084/c01d44a7-9e1c-462f-882d-4530b42f3e71", + "blob:http://127.0.0.1:8084/404d7865-7316-42d4-ad1f-82ddab4a6fc1", + "blob:http://127.0.0.1:8084/c0ab3fa3-cb94-4faa-95ee-10a0a409a2bb", + "blob:http://127.0.0.1:8084/655ef861-33f2-469e-a456-42b0e10ef121", + "blob:http://127.0.0.1:8084/7042f1c3-20fd-408b-8550-60abb6b2044d", + "blob:http://127.0.0.1:8084/adbf7c6f-0470-43df-bea0-754920e57201", + "blob:http://127.0.0.1:8084/2a5e9d5a-24f9-4ad3-af06-3c2ed5c976b4", + "blob:http://127.0.0.1:8084/cad56601-f6c5-46b5-b212-d368b81839d9" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 447, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 471, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/a8e95741-faf7-4790-ad50-39f609680bde" + }, + "result": { + "value": "C:\\fakepath\\thumbnail-pattern.mp4", + "created": [ + "blob:http://127.0.0.1:8084/a8e95741-faf7-4790-ad50-39f609680bde", + "blob:http://127.0.0.1:8084/bb0ff9a9-211c-4642-9435-bb3ff5189f59" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/bb0ff9a9-211c-4642-9435-bb3ff5189f59" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 935, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/a265e836-7477-4734-9972-9a2fb3fe7a8b", + "blob:http://127.0.0.1:8084/e8741aed-b257-4226-a2f6-fe613ea0e663" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/a265e836-7477-4734-9972-9a2fb3fe7a8b" + ], + "pendingState": "pending", + "events": [ + "file", + "canvas", + "video", + "destroy", + "update" + ], + "connected": false, + "bytes": 4980 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1413, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1375, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1302, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1344, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 500, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/364ec9f6-47cd-4e8f-8b80-232ff1fc0507", + "second": "blob:http://127.0.0.1:8084/43996349-0000-47ba-b3ef-564f86641a71", + "created": [ + "blob:http://127.0.0.1:8084/d13beac0-25c5-4af7-9666-b04af65ea672", + "blob:http://127.0.0.1:8084/95f89fae-cfc8-4dca-b755-54e9801e5d40", + "blob:http://127.0.0.1:8084/62a3ce2d-deda-49ac-b074-ea614cd7b08e", + "blob:http://127.0.0.1:8084/111acb47-1b67-4a2e-9a6c-f6a79b067a55", + "blob:http://127.0.0.1:8084/d3e0d3c4-5624-4d9a-b97b-741727c6aecf", + "blob:http://127.0.0.1:8084/f6c3ed43-03c5-48a6-b635-f4bf1c8083c1", + "blob:http://127.0.0.1:8084/02843cdd-f330-42e8-b28c-b7e3d9462d1e", + "blob:http://127.0.0.1:8084/2a1b94ac-9bc6-4d81-a2fe-5ce313b03ccd", + "blob:http://127.0.0.1:8084/ea1204bb-11f5-44d9-ae15-c1a78f13ce1e", + "blob:http://127.0.0.1:8084/6bdd58b3-0a9b-41e1-889b-04e81dca2329", + "blob:http://127.0.0.1:8084/364ec9f6-47cd-4e8f-8b80-232ff1fc0507", + "blob:http://127.0.0.1:8084/71cdb94a-a421-456b-a26b-b463d9843e6a", + "blob:http://127.0.0.1:8084/dc08eba0-d81b-42de-aaa7-12f0b64dcb66", + "blob:http://127.0.0.1:8084/cbee3527-db39-46a9-accb-08a34f307896", + "blob:http://127.0.0.1:8084/6b1f98a6-6fd5-4d18-b5bb-38d6d5c998f5", + "blob:http://127.0.0.1:8084/c991584e-860e-4e1e-84ad-85e008863166", + "blob:http://127.0.0.1:8084/4d57a4cf-1ed9-44af-a00d-f8e00ea8ace9", + "blob:http://127.0.0.1:8084/f9aaa86a-d992-4e5d-9011-2fea3498000a", + "blob:http://127.0.0.1:8084/65ee333d-9116-4741-9279-dc3c5bfafb6a", + "blob:http://127.0.0.1:8084/d720430e-b2b9-4694-a91b-a504a2f5b17d", + "blob:http://127.0.0.1:8084/43996349-0000-47ba-b3ef-564f86641a71" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/95f89fae-cfc8-4dca-b755-54e9801e5d40", + "blob:http://127.0.0.1:8084/62a3ce2d-deda-49ac-b074-ea614cd7b08e", + "blob:http://127.0.0.1:8084/111acb47-1b67-4a2e-9a6c-f6a79b067a55", + "blob:http://127.0.0.1:8084/d3e0d3c4-5624-4d9a-b97b-741727c6aecf", + "blob:http://127.0.0.1:8084/f6c3ed43-03c5-48a6-b635-f4bf1c8083c1", + "blob:http://127.0.0.1:8084/02843cdd-f330-42e8-b28c-b7e3d9462d1e", + "blob:http://127.0.0.1:8084/2a1b94ac-9bc6-4d81-a2fe-5ce313b03ccd", + "blob:http://127.0.0.1:8084/ea1204bb-11f5-44d9-ae15-c1a78f13ce1e", + "blob:http://127.0.0.1:8084/6bdd58b3-0a9b-41e1-889b-04e81dca2329", + "blob:http://127.0.0.1:8084/364ec9f6-47cd-4e8f-8b80-232ff1fc0507", + "blob:http://127.0.0.1:8084/71cdb94a-a421-456b-a26b-b463d9843e6a", + "blob:http://127.0.0.1:8084/dc08eba0-d81b-42de-aaa7-12f0b64dcb66", + "blob:http://127.0.0.1:8084/cbee3527-db39-46a9-accb-08a34f307896", + "blob:http://127.0.0.1:8084/6b1f98a6-6fd5-4d18-b5bb-38d6d5c998f5", + "blob:http://127.0.0.1:8084/c991584e-860e-4e1e-84ad-85e008863166", + "blob:http://127.0.0.1:8084/4d57a4cf-1ed9-44af-a00d-f8e00ea8ace9", + "blob:http://127.0.0.1:8084/f9aaa86a-d992-4e5d-9011-2fea3498000a", + "blob:http://127.0.0.1:8084/65ee333d-9116-4741-9279-dc3c5bfafb6a", + "blob:http://127.0.0.1:8084/d720430e-b2b9-4694-a91b-a504a2f5b17d", + "blob:http://127.0.0.1:8084/d13beac0-25c5-4af7-9666-b04af65ea672", + "blob:http://127.0.0.1:8084/43996349-0000-47ba-b3ef-564f86641a71" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 186, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 243, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/39e04d9f-dda1-4f13-8a01-c55d826e6ae6" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/39e04d9f-dda1-4f13-8a01-c55d826e6ae6", + "blob:http://127.0.0.1:8084/de08a497-f346-4ce7-8cf7-1d32c6b72e22" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/de08a497-f346-4ce7-8cf7-1d32c6b72e22" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 350, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/50181f37-78e8-4c27-948f-408893e9ea6f", + "blob:http://127.0.0.1:8084/649cc103-8f29-4948-a150-e081d2be2feb" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/50181f37-78e8-4c27-948f-408893e9ea6f" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 2426, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38560, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/9777b05f-8714-4eb6-a285-5ff2a7130c58", + "second": "blob:http://127.0.0.1:8084/33af18f3-fea4-4c8e-9b31-4b7f0f273ffe", + "created": [ + "blob:http://127.0.0.1:8084/c02512ba-c8e6-4666-86bf-ee48b65fc93c", + "blob:http://127.0.0.1:8084/bd0a0061-3aa5-40a0-b1bc-726052484576", + "blob:http://127.0.0.1:8084/7f3f21ab-b178-4fa0-afd3-3b450a830b3c", + "blob:http://127.0.0.1:8084/bddcbf6e-d2b1-4dc6-8493-43bad65c8871", + "blob:http://127.0.0.1:8084/d1abc605-ee24-4230-a132-265e42f5cc56", + "blob:http://127.0.0.1:8084/21f6133e-8c4e-432a-8e16-9acde7a1594c", + "blob:http://127.0.0.1:8084/7aa5ae80-752d-4d48-a711-1be4b40a13c9", + "blob:http://127.0.0.1:8084/fb5151f0-49cf-4fb0-bb0b-3f83052eca05", + "blob:http://127.0.0.1:8084/305f2a9d-1f56-41e3-9e50-c4cb846405fe", + "blob:http://127.0.0.1:8084/e7eccd37-9943-4680-aab2-cfb6b5416b9a", + "blob:http://127.0.0.1:8084/9777b05f-8714-4eb6-a285-5ff2a7130c58", + "blob:http://127.0.0.1:8084/21df59a3-6c06-42ff-8674-ec094b77399c", + "blob:http://127.0.0.1:8084/7ad8107c-c150-4d05-9f06-f687d1affac9", + "blob:http://127.0.0.1:8084/8a67fc2f-57d0-4a49-9deb-8a1d5a99d9ae", + "blob:http://127.0.0.1:8084/97965dc6-226a-4d87-8227-cf061090ca15", + "blob:http://127.0.0.1:8084/7ba9ab6b-d774-4bdc-a04e-fe532e1a864f", + "blob:http://127.0.0.1:8084/43acd7ad-f575-42d8-82b7-c911a4231ad0", + "blob:http://127.0.0.1:8084/0288c2a1-e147-4b07-9406-b9601e07617b", + "blob:http://127.0.0.1:8084/debdb36f-7490-4941-9b34-e06d64721003", + "blob:http://127.0.0.1:8084/b0c9160c-6fb3-4ee9-baae-d735f2bec09b", + "blob:http://127.0.0.1:8084/33af18f3-fea4-4c8e-9b31-4b7f0f273ffe" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/bd0a0061-3aa5-40a0-b1bc-726052484576", + "blob:http://127.0.0.1:8084/7f3f21ab-b178-4fa0-afd3-3b450a830b3c", + "blob:http://127.0.0.1:8084/bddcbf6e-d2b1-4dc6-8493-43bad65c8871", + "blob:http://127.0.0.1:8084/d1abc605-ee24-4230-a132-265e42f5cc56", + "blob:http://127.0.0.1:8084/21f6133e-8c4e-432a-8e16-9acde7a1594c", + "blob:http://127.0.0.1:8084/7aa5ae80-752d-4d48-a711-1be4b40a13c9", + "blob:http://127.0.0.1:8084/fb5151f0-49cf-4fb0-bb0b-3f83052eca05", + "blob:http://127.0.0.1:8084/305f2a9d-1f56-41e3-9e50-c4cb846405fe", + "blob:http://127.0.0.1:8084/e7eccd37-9943-4680-aab2-cfb6b5416b9a", + "blob:http://127.0.0.1:8084/9777b05f-8714-4eb6-a285-5ff2a7130c58", + "blob:http://127.0.0.1:8084/21df59a3-6c06-42ff-8674-ec094b77399c", + "blob:http://127.0.0.1:8084/7ad8107c-c150-4d05-9f06-f687d1affac9", + "blob:http://127.0.0.1:8084/8a67fc2f-57d0-4a49-9deb-8a1d5a99d9ae", + "blob:http://127.0.0.1:8084/97965dc6-226a-4d87-8227-cf061090ca15", + "blob:http://127.0.0.1:8084/7ba9ab6b-d774-4bdc-a04e-fe532e1a864f", + "blob:http://127.0.0.1:8084/43acd7ad-f575-42d8-82b7-c911a4231ad0", + "blob:http://127.0.0.1:8084/0288c2a1-e147-4b07-9406-b9601e07617b", + "blob:http://127.0.0.1:8084/debdb36f-7490-4941-9b34-e06d64721003", + "blob:http://127.0.0.1:8084/b0c9160c-6fb3-4ee9-baae-d735f2bec09b", + "blob:http://127.0.0.1:8084/c02512ba-c8e6-4666-86bf-ee48b65fc93c", + "blob:http://127.0.0.1:8084/33af18f3-fea4-4c8e-9b31-4b7f0f273ffe" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 463, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 547, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/9f20bb70-9605-4850-90ec-d7ed3433ea25" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/9f20bb70-9605-4850-90ec-d7ed3433ea25", + "blob:http://127.0.0.1:8084/5d9f02a0-2eaa-4df8-8471-6d14a04a60dc" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/5d9f02a0-2eaa-4df8-8471-6d14a04a60dc" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 727, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/18f5d27a-18b7-4fe9-81c1-41272fb45454", + "blob:http://127.0.0.1:8084/cd77b188-d7b1-441a-ac6e-b10b27032222" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/18f5d27a-18b7-4fe9-81c1-41272fb45454" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1340, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1371, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1303, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1362, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 549, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/72afeccf-5f51-420c-b0e3-c00b84c338a8", + "second": "blob:http://127.0.0.1:8084/6a88c4dd-aff7-4806-8bd2-bd75f7e6e7bc", + "created": [ + "blob:http://127.0.0.1:8084/33aecd5f-a621-47f3-a057-52227f14e96c", + "blob:http://127.0.0.1:8084/fc5a0372-d7b8-44a5-ac25-c5b39399b655", + "blob:http://127.0.0.1:8084/b2a9a2f4-e01c-4586-ba15-383449003043", + "blob:http://127.0.0.1:8084/0f9cfc5f-1acf-4758-b21b-310ada0524ce", + "blob:http://127.0.0.1:8084/dab7828c-ede3-4913-b602-998b20f6742f", + "blob:http://127.0.0.1:8084/cf75f876-bdfa-4514-8f7d-d483cb1e3b8c", + "blob:http://127.0.0.1:8084/0b914eca-c614-4085-a83e-cc866901e30e", + "blob:http://127.0.0.1:8084/03f57ec1-60fe-4b99-8bce-1a3f0ac54aad", + "blob:http://127.0.0.1:8084/f86decd7-ea22-4178-ab2c-52edb295b1a5", + "blob:http://127.0.0.1:8084/57a51954-abea-4f7d-b6da-befedf17c585", + "blob:http://127.0.0.1:8084/72afeccf-5f51-420c-b0e3-c00b84c338a8", + "blob:http://127.0.0.1:8084/6cfcb176-d79b-4ebe-93c2-d30243ffe1a0", + "blob:http://127.0.0.1:8084/27f1749b-c8ac-49f1-964b-61f194fe1239", + "blob:http://127.0.0.1:8084/38e70f84-ead8-430d-91b3-13ea96c89f73", + "blob:http://127.0.0.1:8084/216230f1-d679-4dc7-a6d1-d0442e9b30aa", + "blob:http://127.0.0.1:8084/4331d5d9-1eea-4a1f-957d-0b097bb99011", + "blob:http://127.0.0.1:8084/1ee568f8-583a-4881-a6bc-ac93f7d20467", + "blob:http://127.0.0.1:8084/7efd3670-0491-41de-a1c6-8065f488a524", + "blob:http://127.0.0.1:8084/74fe2e16-d906-4a04-91d2-5e4adbc35cc5", + "blob:http://127.0.0.1:8084/4b5febab-6b56-43f5-ac24-12962dfab97d", + "blob:http://127.0.0.1:8084/6a88c4dd-aff7-4806-8bd2-bd75f7e6e7bc" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/fc5a0372-d7b8-44a5-ac25-c5b39399b655", + "blob:http://127.0.0.1:8084/b2a9a2f4-e01c-4586-ba15-383449003043", + "blob:http://127.0.0.1:8084/0f9cfc5f-1acf-4758-b21b-310ada0524ce", + "blob:http://127.0.0.1:8084/dab7828c-ede3-4913-b602-998b20f6742f", + "blob:http://127.0.0.1:8084/cf75f876-bdfa-4514-8f7d-d483cb1e3b8c", + "blob:http://127.0.0.1:8084/0b914eca-c614-4085-a83e-cc866901e30e", + "blob:http://127.0.0.1:8084/03f57ec1-60fe-4b99-8bce-1a3f0ac54aad", + "blob:http://127.0.0.1:8084/f86decd7-ea22-4178-ab2c-52edb295b1a5", + "blob:http://127.0.0.1:8084/57a51954-abea-4f7d-b6da-befedf17c585", + "blob:http://127.0.0.1:8084/72afeccf-5f51-420c-b0e3-c00b84c338a8", + "blob:http://127.0.0.1:8084/6cfcb176-d79b-4ebe-93c2-d30243ffe1a0", + "blob:http://127.0.0.1:8084/27f1749b-c8ac-49f1-964b-61f194fe1239", + "blob:http://127.0.0.1:8084/38e70f84-ead8-430d-91b3-13ea96c89f73", + "blob:http://127.0.0.1:8084/216230f1-d679-4dc7-a6d1-d0442e9b30aa", + "blob:http://127.0.0.1:8084/4331d5d9-1eea-4a1f-957d-0b097bb99011", + "blob:http://127.0.0.1:8084/1ee568f8-583a-4881-a6bc-ac93f7d20467", + "blob:http://127.0.0.1:8084/7efd3670-0491-41de-a1c6-8065f488a524", + "blob:http://127.0.0.1:8084/74fe2e16-d906-4a04-91d2-5e4adbc35cc5", + "blob:http://127.0.0.1:8084/4b5febab-6b56-43f5-ac24-12962dfab97d", + "blob:http://127.0.0.1:8084/33aecd5f-a621-47f3-a057-52227f14e96c", + "blob:http://127.0.0.1:8084/6a88c4dd-aff7-4806-8bd2-bd75f7e6e7bc" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 187, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 225, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/2d2a868c-1a41-46ac-97ea-a0ed072d47a1" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/2d2a868c-1a41-46ac-97ea-a0ed072d47a1", + "blob:http://127.0.0.1:8084/2bcd60e5-a3da-491d-8603-8ceca750bb49" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/2bcd60e5-a3da-491d-8603-8ceca750bb49" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 356, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/c486aead-07d9-412b-97a6-da16a6564b64", + "blob:http://127.0.0.1:8084/b18f6462-d604-430b-a981-7aac8452a726" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/c486aead-07d9-412b-97a6-da16a6564b64" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1674, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38560, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/0b68f134-26e6-4c19-837b-d60b994c3da8", + "second": "blob:http://127.0.0.1:8084/37c26217-a4b4-4f3d-8fcb-d4135d091100", + "created": [ + "blob:http://127.0.0.1:8084/4adc28ac-0608-49f6-a969-1f72602958c6", + "blob:http://127.0.0.1:8084/86b45910-c18f-45be-af48-5ad46dd884e8", + "blob:http://127.0.0.1:8084/84a09f32-9484-40d2-989d-a0c413949899", + "blob:http://127.0.0.1:8084/8bfa9595-044b-421d-b351-8a2be20f6a4a", + "blob:http://127.0.0.1:8084/e0fabc87-3d7a-4366-8955-364b751783d5", + "blob:http://127.0.0.1:8084/6fdec7af-87b7-462d-a6f8-b4ba3f92273b", + "blob:http://127.0.0.1:8084/ad9a2639-f05e-457a-9efc-b55c0e441518", + "blob:http://127.0.0.1:8084/af316938-2f67-4668-8580-748459249a4e", + "blob:http://127.0.0.1:8084/3036f5fe-57fd-404b-8f97-79f35746c957", + "blob:http://127.0.0.1:8084/1064b5ae-1a53-41fc-97d3-750885bfd96c", + "blob:http://127.0.0.1:8084/0b68f134-26e6-4c19-837b-d60b994c3da8", + "blob:http://127.0.0.1:8084/1bb1a17a-5268-49f0-a729-81b6e9a887b3", + "blob:http://127.0.0.1:8084/3ec833ad-6f81-4553-843b-79dae74d9569", + "blob:http://127.0.0.1:8084/95fa66d6-14c8-42ba-9042-c83bd3cc2a07", + "blob:http://127.0.0.1:8084/21173820-8335-401a-ace0-9fefcf79cbe9", + "blob:http://127.0.0.1:8084/da567327-eb03-4139-85a5-a5eb7f0faf1b", + "blob:http://127.0.0.1:8084/aba7a15d-04d3-4795-815e-8db5a136aa2d", + "blob:http://127.0.0.1:8084/fde60066-2d22-4e0c-b137-c055a58e4a17", + "blob:http://127.0.0.1:8084/20ce7d49-d33d-4399-b2e0-f1663719ec06", + "blob:http://127.0.0.1:8084/d3804ff7-ef41-40a0-9a36-5e73496fed31", + "blob:http://127.0.0.1:8084/37c26217-a4b4-4f3d-8fcb-d4135d091100" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/86b45910-c18f-45be-af48-5ad46dd884e8", + "blob:http://127.0.0.1:8084/84a09f32-9484-40d2-989d-a0c413949899", + "blob:http://127.0.0.1:8084/8bfa9595-044b-421d-b351-8a2be20f6a4a", + "blob:http://127.0.0.1:8084/e0fabc87-3d7a-4366-8955-364b751783d5", + "blob:http://127.0.0.1:8084/6fdec7af-87b7-462d-a6f8-b4ba3f92273b", + "blob:http://127.0.0.1:8084/ad9a2639-f05e-457a-9efc-b55c0e441518", + "blob:http://127.0.0.1:8084/af316938-2f67-4668-8580-748459249a4e", + "blob:http://127.0.0.1:8084/3036f5fe-57fd-404b-8f97-79f35746c957", + "blob:http://127.0.0.1:8084/1064b5ae-1a53-41fc-97d3-750885bfd96c", + "blob:http://127.0.0.1:8084/0b68f134-26e6-4c19-837b-d60b994c3da8", + "blob:http://127.0.0.1:8084/1bb1a17a-5268-49f0-a729-81b6e9a887b3", + "blob:http://127.0.0.1:8084/3ec833ad-6f81-4553-843b-79dae74d9569", + "blob:http://127.0.0.1:8084/95fa66d6-14c8-42ba-9042-c83bd3cc2a07", + "blob:http://127.0.0.1:8084/21173820-8335-401a-ace0-9fefcf79cbe9", + "blob:http://127.0.0.1:8084/da567327-eb03-4139-85a5-a5eb7f0faf1b", + "blob:http://127.0.0.1:8084/aba7a15d-04d3-4795-815e-8db5a136aa2d", + "blob:http://127.0.0.1:8084/fde60066-2d22-4e0c-b137-c055a58e4a17", + "blob:http://127.0.0.1:8084/20ce7d49-d33d-4399-b2e0-f1663719ec06", + "blob:http://127.0.0.1:8084/d3804ff7-ef41-40a0-9a36-5e73496fed31", + "blob:http://127.0.0.1:8084/4adc28ac-0608-49f6-a969-1f72602958c6", + "blob:http://127.0.0.1:8084/37c26217-a4b4-4f3d-8fcb-d4135d091100" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 444, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1202, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/4f29504e-588d-413d-93e2-9061ebd821d6" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/4f29504e-588d-413d-93e2-9061ebd821d6", + "blob:http://127.0.0.1:8084/4f21806d-d81a-4293-8eb0-52c51107e08f" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/4f21806d-d81a-4293-8eb0-52c51107e08f" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 706, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/a28ad3bc-201d-4da3-b905-1bf38f161b04", + "blob:http://127.0.0.1:8084/9c5d4233-b895-420b-a0d3-e71b81da1c49" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/a28ad3bc-201d-4da3-b905-1bf38f161b04" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1438, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1406, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1315, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1372, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 523, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/eda751ff-e2ab-4cd3-ad3a-010e3167fb3d", + "second": "blob:http://127.0.0.1:8084/9daa7bad-c6d9-46c6-b03a-5bfa7b35a2b6", + "created": [ + "blob:http://127.0.0.1:8084/eede5878-da70-4779-9c6f-4ef3816cd8b3", + "blob:http://127.0.0.1:8084/839900d8-0fe9-4c70-b876-2b470130a820", + "blob:http://127.0.0.1:8084/22d9e8c7-1d5d-4b1d-9da6-b3f706f36362", + "blob:http://127.0.0.1:8084/e32cf0f0-e00e-4277-986c-37f4dcbc52b2", + "blob:http://127.0.0.1:8084/f2ba0961-d38a-478d-a2d1-b6f2db9702cb", + "blob:http://127.0.0.1:8084/68a18446-c967-4320-8fa6-875b26e5627e", + "blob:http://127.0.0.1:8084/64390e44-9fb4-4b68-9e48-bb6920c3396d", + "blob:http://127.0.0.1:8084/4d9445bb-28f3-4991-ab4f-4e2578443d8c", + "blob:http://127.0.0.1:8084/1c03a3d7-cb40-40ec-bd0b-f31fe8d56ce0", + "blob:http://127.0.0.1:8084/9afee817-e077-44af-87bf-405abf41cbbd", + "blob:http://127.0.0.1:8084/eda751ff-e2ab-4cd3-ad3a-010e3167fb3d", + "blob:http://127.0.0.1:8084/89903525-d407-4760-96e0-f4e190c675dc", + "blob:http://127.0.0.1:8084/3d6c5dbe-ec77-437c-ba9f-0c72ec6cee48", + "blob:http://127.0.0.1:8084/6795f8e8-55c8-4460-9d16-f615a9cc6174", + "blob:http://127.0.0.1:8084/1d343b47-8d2e-4803-8268-bb3728a249b9", + "blob:http://127.0.0.1:8084/057cbdd9-4898-4921-be50-60e9d99f76c1", + "blob:http://127.0.0.1:8084/8a1d7c0d-9b92-47db-96f5-579945447ed3", + "blob:http://127.0.0.1:8084/89709d55-cc44-4bf7-9db1-d0f2836c771f", + "blob:http://127.0.0.1:8084/39100bbe-d003-425e-b7c0-b5f5eb6be55b", + "blob:http://127.0.0.1:8084/8e33142e-5021-48fc-94c5-2c58e08ecca3", + "blob:http://127.0.0.1:8084/9daa7bad-c6d9-46c6-b03a-5bfa7b35a2b6" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/839900d8-0fe9-4c70-b876-2b470130a820", + "blob:http://127.0.0.1:8084/22d9e8c7-1d5d-4b1d-9da6-b3f706f36362", + "blob:http://127.0.0.1:8084/e32cf0f0-e00e-4277-986c-37f4dcbc52b2", + "blob:http://127.0.0.1:8084/f2ba0961-d38a-478d-a2d1-b6f2db9702cb", + "blob:http://127.0.0.1:8084/68a18446-c967-4320-8fa6-875b26e5627e", + "blob:http://127.0.0.1:8084/64390e44-9fb4-4b68-9e48-bb6920c3396d", + "blob:http://127.0.0.1:8084/4d9445bb-28f3-4991-ab4f-4e2578443d8c", + "blob:http://127.0.0.1:8084/1c03a3d7-cb40-40ec-bd0b-f31fe8d56ce0", + "blob:http://127.0.0.1:8084/9afee817-e077-44af-87bf-405abf41cbbd", + "blob:http://127.0.0.1:8084/eda751ff-e2ab-4cd3-ad3a-010e3167fb3d", + "blob:http://127.0.0.1:8084/89903525-d407-4760-96e0-f4e190c675dc", + "blob:http://127.0.0.1:8084/3d6c5dbe-ec77-437c-ba9f-0c72ec6cee48", + "blob:http://127.0.0.1:8084/6795f8e8-55c8-4460-9d16-f615a9cc6174", + "blob:http://127.0.0.1:8084/1d343b47-8d2e-4803-8268-bb3728a249b9", + "blob:http://127.0.0.1:8084/057cbdd9-4898-4921-be50-60e9d99f76c1", + "blob:http://127.0.0.1:8084/8a1d7c0d-9b92-47db-96f5-579945447ed3", + "blob:http://127.0.0.1:8084/89709d55-cc44-4bf7-9db1-d0f2836c771f", + "blob:http://127.0.0.1:8084/39100bbe-d003-425e-b7c0-b5f5eb6be55b", + "blob:http://127.0.0.1:8084/8e33142e-5021-48fc-94c5-2c58e08ecca3", + "blob:http://127.0.0.1:8084/eede5878-da70-4779-9c6f-4ef3816cd8b3", + "blob:http://127.0.0.1:8084/9daa7bad-c6d9-46c6-b03a-5bfa7b35a2b6" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 183, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 226, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/69abc1f1-2645-4059-ba81-438731c59d1d" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/69abc1f1-2645-4059-ba81-438731c59d1d", + "blob:http://127.0.0.1:8084/55d89534-a660-420b-9f79-9af6f8b8d6d2" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/55d89534-a660-420b-9f79-9af6f8b8d6d2" + ] + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 352, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/49e4c4bd-afd5-4db9-9f6e-4aa68971eb01", + "blob:http://127.0.0.1:8084/58e1820e-ebf0-4e17-8d34-a70148af96b1" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/49e4c4bd-afd5-4db9-9f6e-4aa68971eb01" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1514, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38895, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/854db0c5-3983-44b2-9d18-a1ac40fc675f", + "second": "blob:http://127.0.0.1:8084/9da6e162-dbf0-46fd-877a-11e91cb65e2d", + "created": [ + "blob:http://127.0.0.1:8084/d9963f2f-caa7-40f2-94a2-9f76c6e2a946", + "blob:http://127.0.0.1:8084/3c236716-7ad0-40af-a872-0958aafbef92", + "blob:http://127.0.0.1:8084/4d6710a0-41fd-4324-bdcd-9972c031d473", + "blob:http://127.0.0.1:8084/e5a56978-d4eb-48bd-84a4-c5dc9dcc8814", + "blob:http://127.0.0.1:8084/149a5136-83a1-4d33-a149-eb0f5ad84428", + "blob:http://127.0.0.1:8084/3a235874-df31-4051-be11-cac1d822718d", + "blob:http://127.0.0.1:8084/4a5856d9-0ba4-47d8-9c70-b70084236bbb", + "blob:http://127.0.0.1:8084/b497ea6b-e583-4639-ad23-b966de71f36d", + "blob:http://127.0.0.1:8084/13d18d07-461e-4c78-9886-3fff8a0c1eda", + "blob:http://127.0.0.1:8084/4159cc0b-c420-430b-8870-303e0047f043", + "blob:http://127.0.0.1:8084/854db0c5-3983-44b2-9d18-a1ac40fc675f", + "blob:http://127.0.0.1:8084/62f18b3c-1d30-46d5-91b4-abe8406d6c4a", + "blob:http://127.0.0.1:8084/4bd87cba-3fff-4a1d-9460-2d55ec8bbe57", + "blob:http://127.0.0.1:8084/71deed0e-8e0d-4973-9471-a28b16db7700", + "blob:http://127.0.0.1:8084/5cbf5261-3c04-491e-86c7-e55b6ac580e8", + "blob:http://127.0.0.1:8084/87c4a833-7c39-4e68-8d55-b8889abe7c55", + "blob:http://127.0.0.1:8084/372ec1eb-4947-4caf-bffe-6273fa5ddd1b", + "blob:http://127.0.0.1:8084/7bb9a979-13b1-48ff-96d6-f53363565932", + "blob:http://127.0.0.1:8084/cf6e8936-8adb-431c-9e8a-921a49c7274c", + "blob:http://127.0.0.1:8084/9ef1af20-12ce-4751-9b75-b5d5dc3eceef", + "blob:http://127.0.0.1:8084/9da6e162-dbf0-46fd-877a-11e91cb65e2d" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/3c236716-7ad0-40af-a872-0958aafbef92", + "blob:http://127.0.0.1:8084/4d6710a0-41fd-4324-bdcd-9972c031d473", + "blob:http://127.0.0.1:8084/e5a56978-d4eb-48bd-84a4-c5dc9dcc8814", + "blob:http://127.0.0.1:8084/149a5136-83a1-4d33-a149-eb0f5ad84428", + "blob:http://127.0.0.1:8084/3a235874-df31-4051-be11-cac1d822718d", + "blob:http://127.0.0.1:8084/4a5856d9-0ba4-47d8-9c70-b70084236bbb", + "blob:http://127.0.0.1:8084/b497ea6b-e583-4639-ad23-b966de71f36d", + "blob:http://127.0.0.1:8084/13d18d07-461e-4c78-9886-3fff8a0c1eda", + "blob:http://127.0.0.1:8084/4159cc0b-c420-430b-8870-303e0047f043", + "blob:http://127.0.0.1:8084/854db0c5-3983-44b2-9d18-a1ac40fc675f", + "blob:http://127.0.0.1:8084/62f18b3c-1d30-46d5-91b4-abe8406d6c4a", + "blob:http://127.0.0.1:8084/4bd87cba-3fff-4a1d-9460-2d55ec8bbe57", + "blob:http://127.0.0.1:8084/71deed0e-8e0d-4973-9471-a28b16db7700", + "blob:http://127.0.0.1:8084/5cbf5261-3c04-491e-86c7-e55b6ac580e8", + "blob:http://127.0.0.1:8084/87c4a833-7c39-4e68-8d55-b8889abe7c55", + "blob:http://127.0.0.1:8084/372ec1eb-4947-4caf-bffe-6273fa5ddd1b", + "blob:http://127.0.0.1:8084/7bb9a979-13b1-48ff-96d6-f53363565932", + "blob:http://127.0.0.1:8084/cf6e8936-8adb-431c-9e8a-921a49c7274c", + "blob:http://127.0.0.1:8084/9ef1af20-12ce-4751-9b75-b5d5dc3eceef", + "blob:http://127.0.0.1:8084/d9963f2f-caa7-40f2-94a2-9f76c6e2a946", + "blob:http://127.0.0.1:8084/9da6e162-dbf0-46fd-877a-11e91cb65e2d" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 502, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 566, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/fac16594-e074-46e2-bbbf-5c827e61c6b5" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/fac16594-e074-46e2-bbbf-5c827e61c6b5", + "blob:http://127.0.0.1:8084/3bc1dbc4-67ea-4bf0-aa98-415ef56e5982" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/3bc1dbc4-67ea-4bf0-aa98-415ef56e5982" + ] + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 591, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/a63824ec-bd53-46d8-95ca-f93f558c424c", + "blob:http://127.0.0.1:8084/97b14922-973a-42cf-a22e-9775b1531758" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/a63824ec-bd53-46d8-95ca-f93f558c424c" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1405, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1297, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1342, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-source / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1257, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-source", + "sha256": "5b4e2c537fc8e5cd8bd201199a7d23213ed062f920e6d2df08782961946f6611", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + } + ] + }, + { + "variant": "main", + "counts": { + "candidate-native-input": 3, + "native-media-control": 3, + "blob-unavailable-control": 16, + "actual-tool-scenario": 32 + }, + "cases": [ + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "chromium", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 271, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "firefox", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 1819, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "webkit", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 816, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "chromium", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 254, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.046009, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.046009, + "width": 640 + } + ] + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "firefox", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 1988, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.045986, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.045986, + "width": 640 + } + ] + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "webkit", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 2024, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 3, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 2, + "error": 0, + "duration": 90.094, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + } + ] + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 8095, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 150, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 30, + "mime": "image/png", + "bytes": 26427, + "nonBlack": 2400, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/fb5dddf3-c666-4bde-a2b6-367313ae6fde", + "second": "blob:http://127.0.0.1:8084/834a8b87-003c-4df7-a422-fcdc9e400fba", + "created": [ + "blob:http://127.0.0.1:8084/6669b5bf-3220-4f13-bbd0-847239a9d045", + "blob:http://127.0.0.1:8084/015f480e-9324-472f-bc95-5fe162906785", + "blob:http://127.0.0.1:8084/da155030-a06c-4d1f-85cc-46920c410e7b", + "blob:http://127.0.0.1:8084/d04b03ea-cf2b-45e7-bb9d-1c7642c0d546", + "blob:http://127.0.0.1:8084/4104c03f-8177-450e-a2e0-b82d7dbec8ad", + "blob:http://127.0.0.1:8084/ccce417e-1a6f-4b25-a572-6519e28ddcdf", + "blob:http://127.0.0.1:8084/41fcaed1-dd03-40be-b281-bb404befa8d7", + "blob:http://127.0.0.1:8084/18264282-fd45-475a-b3d7-8432f38b85dd", + "blob:http://127.0.0.1:8084/be8f1140-3e85-4036-b82e-d439241613b0", + "blob:http://127.0.0.1:8084/24d2fc30-ac8c-466a-a462-34e342aad0c2", + "blob:http://127.0.0.1:8084/fb5dddf3-c666-4bde-a2b6-367313ae6fde", + "blob:http://127.0.0.1:8084/4e81b4c3-ba14-4b4b-bb83-053a70199aab", + "blob:http://127.0.0.1:8084/5765fec1-66dc-46f7-8d50-bea951bd1ee7", + "blob:http://127.0.0.1:8084/22b4ac08-8653-4b44-a5ef-4df262ecb6f6", + "blob:http://127.0.0.1:8084/550f302a-80ae-4eeb-9beb-0da4c2b39173", + "blob:http://127.0.0.1:8084/27e39476-1aa4-462e-bc0d-23c80e85be5d", + "blob:http://127.0.0.1:8084/479ea002-043f-43dc-8db8-95f4d16e8766", + "blob:http://127.0.0.1:8084/63a2c2dc-8fa1-4ed0-aaf4-778ef4a42fc5", + "blob:http://127.0.0.1:8084/ab8340e4-3e5b-4d52-a39f-9f829f856e5e", + "blob:http://127.0.0.1:8084/be60ed89-3316-49aa-863c-73de77454bcf", + "blob:http://127.0.0.1:8084/834a8b87-003c-4df7-a422-fcdc9e400fba" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/015f480e-9324-472f-bc95-5fe162906785", + "blob:http://127.0.0.1:8084/da155030-a06c-4d1f-85cc-46920c410e7b", + "blob:http://127.0.0.1:8084/d04b03ea-cf2b-45e7-bb9d-1c7642c0d546", + "blob:http://127.0.0.1:8084/4104c03f-8177-450e-a2e0-b82d7dbec8ad", + "blob:http://127.0.0.1:8084/ccce417e-1a6f-4b25-a572-6519e28ddcdf", + "blob:http://127.0.0.1:8084/41fcaed1-dd03-40be-b281-bb404befa8d7", + "blob:http://127.0.0.1:8084/18264282-fd45-475a-b3d7-8432f38b85dd", + "blob:http://127.0.0.1:8084/be8f1140-3e85-4036-b82e-d439241613b0", + "blob:http://127.0.0.1:8084/24d2fc30-ac8c-466a-a462-34e342aad0c2", + "blob:http://127.0.0.1:8084/fb5dddf3-c666-4bde-a2b6-367313ae6fde", + "blob:http://127.0.0.1:8084/4e81b4c3-ba14-4b4b-bb83-053a70199aab", + "blob:http://127.0.0.1:8084/5765fec1-66dc-46f7-8d50-bea951bd1ee7", + "blob:http://127.0.0.1:8084/22b4ac08-8653-4b44-a5ef-4df262ecb6f6", + "blob:http://127.0.0.1:8084/550f302a-80ae-4eeb-9beb-0da4c2b39173", + "blob:http://127.0.0.1:8084/27e39476-1aa4-462e-bc0d-23c80e85be5d", + "blob:http://127.0.0.1:8084/479ea002-043f-43dc-8db8-95f4d16e8766", + "blob:http://127.0.0.1:8084/63a2c2dc-8fa1-4ed0-aaf4-778ef4a42fc5", + "blob:http://127.0.0.1:8084/ab8340e4-3e5b-4d52-a39f-9f829f856e5e", + "blob:http://127.0.0.1:8084/be60ed89-3316-49aa-863c-73de77454bcf", + "blob:http://127.0.0.1:8084/6669b5bf-3220-4f13-bbd0-847239a9d045", + "blob:http://127.0.0.1:8084/834a8b87-003c-4df7-a422-fcdc9e400fba" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 221, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 249, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/e5b44bad-324e-454a-a0e4-6a945f7ad119" + }, + "result": { + "value": "C:\\fakepath\\thumbnail-pattern.mp4", + "created": [ + "blob:http://127.0.0.1:8084/e5b44bad-324e-454a-a0e4-6a945f7ad119", + "blob:http://127.0.0.1:8084/5809ba27-c138-4c99-977c-f0c2ecd09f9c" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/5809ba27-c138-4c99-977c-f0c2ecd09f9c" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 620, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/c770b3ae-e191-4641-91b3-b502aa858e9d", + "blob:http://127.0.0.1:8084/b3dc43e4-6765-42fc-bc86-fc0526583d30" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/c770b3ae-e191-4641-91b3-b502aa858e9d" + ], + "pendingState": "pending", + "events": [ + "file", + "canvas", + "video", + "destroy", + "update" + ], + "connected": false, + "bytes": 7540 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 8255, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 150, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 30, + "mime": "image/png", + "bytes": 20020, + "nonBlack": 2400, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/e51360f8-b5ca-4526-a61b-865ad35fea87", + "second": "blob:http://127.0.0.1:8084/cfe0f179-a1e5-44c9-ad97-04cfe302b402", + "created": [ + "blob:http://127.0.0.1:8084/3319903c-f9c1-4708-a2f3-cf57224e35c5", + "blob:http://127.0.0.1:8084/22b78f53-ec68-4725-a139-d8065e7a5af7", + "blob:http://127.0.0.1:8084/78ebb2dc-14ee-43f2-9690-da25172684bc", + "blob:http://127.0.0.1:8084/4aeeeee3-1bf7-466d-805b-f99643075d3d", + "blob:http://127.0.0.1:8084/811aaa54-066c-4320-b160-c9bca15ee805", + "blob:http://127.0.0.1:8084/69c9639e-833a-41b2-ad23-9dda25925a19", + "blob:http://127.0.0.1:8084/6a28e6d9-76fd-4846-828c-cc03ff2a74ec", + "blob:http://127.0.0.1:8084/8304f187-f964-4b0d-a590-381b4722f4f3", + "blob:http://127.0.0.1:8084/7acd3a8c-6aba-40f0-b5e3-be9efb040aef", + "blob:http://127.0.0.1:8084/fa0a1c64-32fd-4fc5-88a0-dee18478a86a", + "blob:http://127.0.0.1:8084/e51360f8-b5ca-4526-a61b-865ad35fea87", + "blob:http://127.0.0.1:8084/a8763c78-b9ea-4be3-ba44-1e1fba08d986", + "blob:http://127.0.0.1:8084/5ec9c33a-a387-489d-a114-0bfe1a751641", + "blob:http://127.0.0.1:8084/f563321f-e827-4b3d-8dc9-b96f9f214a99", + "blob:http://127.0.0.1:8084/f0603991-35ef-4810-95f3-20da2385bd0f", + "blob:http://127.0.0.1:8084/a21fed87-5fd4-4757-bed0-09edc64d92f4", + "blob:http://127.0.0.1:8084/d01ffe68-a9e3-4cd1-861f-70478cfd8741", + "blob:http://127.0.0.1:8084/dff5dd95-223b-47bc-a8ec-d6ca919580a3", + "blob:http://127.0.0.1:8084/ca92704d-4a65-44a1-987c-a0edc54e8741", + "blob:http://127.0.0.1:8084/0cf60f3c-8203-44d7-bad5-b71bb0850835", + "blob:http://127.0.0.1:8084/cfe0f179-a1e5-44c9-ad97-04cfe302b402" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/22b78f53-ec68-4725-a139-d8065e7a5af7", + "blob:http://127.0.0.1:8084/78ebb2dc-14ee-43f2-9690-da25172684bc", + "blob:http://127.0.0.1:8084/4aeeeee3-1bf7-466d-805b-f99643075d3d", + "blob:http://127.0.0.1:8084/811aaa54-066c-4320-b160-c9bca15ee805", + "blob:http://127.0.0.1:8084/69c9639e-833a-41b2-ad23-9dda25925a19", + "blob:http://127.0.0.1:8084/6a28e6d9-76fd-4846-828c-cc03ff2a74ec", + "blob:http://127.0.0.1:8084/8304f187-f964-4b0d-a590-381b4722f4f3", + "blob:http://127.0.0.1:8084/7acd3a8c-6aba-40f0-b5e3-be9efb040aef", + "blob:http://127.0.0.1:8084/fa0a1c64-32fd-4fc5-88a0-dee18478a86a", + "blob:http://127.0.0.1:8084/e51360f8-b5ca-4526-a61b-865ad35fea87", + "blob:http://127.0.0.1:8084/a8763c78-b9ea-4be3-ba44-1e1fba08d986", + "blob:http://127.0.0.1:8084/5ec9c33a-a387-489d-a114-0bfe1a751641", + "blob:http://127.0.0.1:8084/f563321f-e827-4b3d-8dc9-b96f9f214a99", + "blob:http://127.0.0.1:8084/f0603991-35ef-4810-95f3-20da2385bd0f", + "blob:http://127.0.0.1:8084/a21fed87-5fd4-4757-bed0-09edc64d92f4", + "blob:http://127.0.0.1:8084/d01ffe68-a9e3-4cd1-861f-70478cfd8741", + "blob:http://127.0.0.1:8084/dff5dd95-223b-47bc-a8ec-d6ca919580a3", + "blob:http://127.0.0.1:8084/ca92704d-4a65-44a1-987c-a0edc54e8741", + "blob:http://127.0.0.1:8084/0cf60f3c-8203-44d7-bad5-b71bb0850835", + "blob:http://127.0.0.1:8084/3319903c-f9c1-4708-a2f3-cf57224e35c5", + "blob:http://127.0.0.1:8084/cfe0f179-a1e5-44c9-ad97-04cfe302b402" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 417, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 653, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/ca89ffcc-74b0-43d9-aaab-9a17fde4a11d" + }, + "result": { + "value": "C:\\fakepath\\thumbnail-pattern.mp4", + "created": [ + "blob:http://127.0.0.1:8084/ca89ffcc-74b0-43d9-aaab-9a17fde4a11d", + "blob:http://127.0.0.1:8084/1870d6d0-41d9-4207-b70a-2722e0e52997" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/1870d6d0-41d9-4207-b70a-2722e0e52997" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1818, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/8d74fccb-5fb4-44de-af9e-7dff7afc5e6a", + "blob:http://127.0.0.1:8084/6c546ad9-328d-4f48-9b01-30e5309be2cd" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/8d74fccb-5fb4-44de-af9e-7dff7afc5e6a" + ], + "pendingState": "pending", + "events": [ + "file", + "canvas", + "video", + "destroy", + "update" + ], + "connected": false, + "bytes": 4980 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1340, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1235, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1281, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1376, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 524, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/f0685f1e-b13c-4f77-87fd-858a3acb1727", + "second": "blob:http://127.0.0.1:8084/92c3be66-c564-4a52-8f80-0b72e56e6224", + "created": [ + "blob:http://127.0.0.1:8084/61a2d9a3-3c8a-4e8f-b104-78d32f1d814e", + "blob:http://127.0.0.1:8084/2f94ce27-6823-4b53-94ee-89c6254afa67", + "blob:http://127.0.0.1:8084/c1786ece-6dc5-487c-8f91-95ed32b6a362", + "blob:http://127.0.0.1:8084/7abddc81-b98e-4bec-afc5-d4898bcc6557", + "blob:http://127.0.0.1:8084/4f7b5503-a2b1-45c5-b223-efc86ec99ee8", + "blob:http://127.0.0.1:8084/bff71cab-b773-4d0f-b9ae-9cf15c94f56e", + "blob:http://127.0.0.1:8084/4442dad5-cfb9-4112-b0cf-5d313187fcaa", + "blob:http://127.0.0.1:8084/8d6cf30e-cd40-4a66-a717-0e39678a2867", + "blob:http://127.0.0.1:8084/d8f76a9f-160f-4d99-aa82-e3746e8414fa", + "blob:http://127.0.0.1:8084/648236a6-a650-4749-8dbb-2f0e0cf86ee0", + "blob:http://127.0.0.1:8084/f0685f1e-b13c-4f77-87fd-858a3acb1727", + "blob:http://127.0.0.1:8084/d6f8ea2d-63fb-499c-a012-40c9f01d6b8a", + "blob:http://127.0.0.1:8084/5da7d9c9-ca14-46de-a125-4958cb28c540", + "blob:http://127.0.0.1:8084/0fd6b0b1-3422-4dfb-8244-62655f0c79e8", + "blob:http://127.0.0.1:8084/6f96dc2e-5bef-4a54-bcad-b29e1215c68b", + "blob:http://127.0.0.1:8084/8c96d99b-e3e9-4616-8c60-539aa0210910", + "blob:http://127.0.0.1:8084/a9c6428f-a49d-48ec-ab16-9d13505ac1c7", + "blob:http://127.0.0.1:8084/a17cc1ad-150f-4ea4-8571-bb5a223591fd", + "blob:http://127.0.0.1:8084/abcf9698-464c-4d1c-8bd8-1dab8e0ed8ae", + "blob:http://127.0.0.1:8084/29f7ef43-298d-46c3-80e1-8ee61559728d", + "blob:http://127.0.0.1:8084/92c3be66-c564-4a52-8f80-0b72e56e6224" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/2f94ce27-6823-4b53-94ee-89c6254afa67", + "blob:http://127.0.0.1:8084/c1786ece-6dc5-487c-8f91-95ed32b6a362", + "blob:http://127.0.0.1:8084/7abddc81-b98e-4bec-afc5-d4898bcc6557", + "blob:http://127.0.0.1:8084/4f7b5503-a2b1-45c5-b223-efc86ec99ee8", + "blob:http://127.0.0.1:8084/bff71cab-b773-4d0f-b9ae-9cf15c94f56e", + "blob:http://127.0.0.1:8084/4442dad5-cfb9-4112-b0cf-5d313187fcaa", + "blob:http://127.0.0.1:8084/8d6cf30e-cd40-4a66-a717-0e39678a2867", + "blob:http://127.0.0.1:8084/d8f76a9f-160f-4d99-aa82-e3746e8414fa", + "blob:http://127.0.0.1:8084/648236a6-a650-4749-8dbb-2f0e0cf86ee0", + "blob:http://127.0.0.1:8084/f0685f1e-b13c-4f77-87fd-858a3acb1727", + "blob:http://127.0.0.1:8084/d6f8ea2d-63fb-499c-a012-40c9f01d6b8a", + "blob:http://127.0.0.1:8084/5da7d9c9-ca14-46de-a125-4958cb28c540", + "blob:http://127.0.0.1:8084/0fd6b0b1-3422-4dfb-8244-62655f0c79e8", + "blob:http://127.0.0.1:8084/6f96dc2e-5bef-4a54-bcad-b29e1215c68b", + "blob:http://127.0.0.1:8084/8c96d99b-e3e9-4616-8c60-539aa0210910", + "blob:http://127.0.0.1:8084/a9c6428f-a49d-48ec-ab16-9d13505ac1c7", + "blob:http://127.0.0.1:8084/a17cc1ad-150f-4ea4-8571-bb5a223591fd", + "blob:http://127.0.0.1:8084/abcf9698-464c-4d1c-8bd8-1dab8e0ed8ae", + "blob:http://127.0.0.1:8084/29f7ef43-298d-46c3-80e1-8ee61559728d", + "blob:http://127.0.0.1:8084/61a2d9a3-3c8a-4e8f-b104-78d32f1d814e", + "blob:http://127.0.0.1:8084/92c3be66-c564-4a52-8f80-0b72e56e6224" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 208, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 240, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/1be5844f-59bb-481a-b9f9-23935881ca05" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/1be5844f-59bb-481a-b9f9-23935881ca05", + "blob:http://127.0.0.1:8084/1f1aa78a-543f-465a-b06f-a360211a7e15" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/1f1aa78a-543f-465a-b06f-a360211a7e15" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 371, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/53f3f77b-50aa-4ec3-9dc2-89b6e6a4a9c1", + "blob:http://127.0.0.1:8084/996ddbac-f6b4-4e31-bdfb-e97f9783f33a" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/53f3f77b-50aa-4ec3-9dc2-89b6e6a4a9c1" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1428, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38895, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/4818be7a-983a-4b23-942d-4e35ba5380b8", + "second": "blob:http://127.0.0.1:8084/535041b7-0ef4-4ed9-bf13-f9b550852fe1", + "created": [ + "blob:http://127.0.0.1:8084/3b8fdfe8-4148-4e91-9484-8eaa8e1199c8", + "blob:http://127.0.0.1:8084/f32ceb8d-8eaa-4c85-b6f4-e4bbe231be92", + "blob:http://127.0.0.1:8084/ee8c9cad-f0f8-4055-8878-bcd008da9354", + "blob:http://127.0.0.1:8084/e5000108-cbd0-44d6-81ff-5d00937bb483", + "blob:http://127.0.0.1:8084/e229fd77-d70e-4a01-a59d-4c9540e46af4", + "blob:http://127.0.0.1:8084/22a3d474-659c-4648-a4b4-95c07c151d4b", + "blob:http://127.0.0.1:8084/f908b1bd-0c20-4b0b-a3be-fef61583f5ac", + "blob:http://127.0.0.1:8084/db9935db-b20b-41f4-b897-0e1472d90e9c", + "blob:http://127.0.0.1:8084/3265c6d3-e746-4b2a-adac-cc294a1ca31a", + "blob:http://127.0.0.1:8084/55ecc294-7fb8-459f-80ae-0f20b71130a6", + "blob:http://127.0.0.1:8084/4818be7a-983a-4b23-942d-4e35ba5380b8", + "blob:http://127.0.0.1:8084/33f14a65-a5b7-4171-aaff-64810d0294c1", + "blob:http://127.0.0.1:8084/099ace54-84c7-488f-97da-43bbef63d67c", + "blob:http://127.0.0.1:8084/681d9acf-38be-43ee-86b7-c69b431f7c53", + "blob:http://127.0.0.1:8084/4cc47b5d-0cad-4fce-b0e3-e7afc99693ef", + "blob:http://127.0.0.1:8084/5118aeb1-a961-40c5-ad25-192d1aa73c01", + "blob:http://127.0.0.1:8084/5e17a2a2-1a5f-41f9-b873-f8cbe36135fa", + "blob:http://127.0.0.1:8084/6468b56b-5343-430a-9961-212747d2455c", + "blob:http://127.0.0.1:8084/c71a0f5f-cf4c-4ab5-8149-b8af9a197670", + "blob:http://127.0.0.1:8084/45674e42-ec1c-4bb7-a37a-88713c573bcc", + "blob:http://127.0.0.1:8084/535041b7-0ef4-4ed9-bf13-f9b550852fe1" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/f32ceb8d-8eaa-4c85-b6f4-e4bbe231be92", + "blob:http://127.0.0.1:8084/ee8c9cad-f0f8-4055-8878-bcd008da9354", + "blob:http://127.0.0.1:8084/e5000108-cbd0-44d6-81ff-5d00937bb483", + "blob:http://127.0.0.1:8084/e229fd77-d70e-4a01-a59d-4c9540e46af4", + "blob:http://127.0.0.1:8084/22a3d474-659c-4648-a4b4-95c07c151d4b", + "blob:http://127.0.0.1:8084/f908b1bd-0c20-4b0b-a3be-fef61583f5ac", + "blob:http://127.0.0.1:8084/db9935db-b20b-41f4-b897-0e1472d90e9c", + "blob:http://127.0.0.1:8084/3265c6d3-e746-4b2a-adac-cc294a1ca31a", + "blob:http://127.0.0.1:8084/55ecc294-7fb8-459f-80ae-0f20b71130a6", + "blob:http://127.0.0.1:8084/4818be7a-983a-4b23-942d-4e35ba5380b8", + "blob:http://127.0.0.1:8084/33f14a65-a5b7-4171-aaff-64810d0294c1", + "blob:http://127.0.0.1:8084/099ace54-84c7-488f-97da-43bbef63d67c", + "blob:http://127.0.0.1:8084/681d9acf-38be-43ee-86b7-c69b431f7c53", + "blob:http://127.0.0.1:8084/4cc47b5d-0cad-4fce-b0e3-e7afc99693ef", + "blob:http://127.0.0.1:8084/5118aeb1-a961-40c5-ad25-192d1aa73c01", + "blob:http://127.0.0.1:8084/5e17a2a2-1a5f-41f9-b873-f8cbe36135fa", + "blob:http://127.0.0.1:8084/6468b56b-5343-430a-9961-212747d2455c", + "blob:http://127.0.0.1:8084/c71a0f5f-cf4c-4ab5-8149-b8af9a197670", + "blob:http://127.0.0.1:8084/45674e42-ec1c-4bb7-a37a-88713c573bcc", + "blob:http://127.0.0.1:8084/3b8fdfe8-4148-4e91-9484-8eaa8e1199c8", + "blob:http://127.0.0.1:8084/535041b7-0ef4-4ed9-bf13-f9b550852fe1" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 443, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 584, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/2e128439-7d67-4f5b-a6f6-c319f4a6efb8" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/2e128439-7d67-4f5b-a6f6-c319f4a6efb8", + "blob:http://127.0.0.1:8084/8f6e51aa-59bb-47f2-90e4-1dd4c1755d2d" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/8f6e51aa-59bb-47f2-90e4-1dd4c1755d2d" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 691, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/ab206350-dfbb-4f36-9a94-97fe94ac447b", + "blob:http://127.0.0.1:8084/ed2cd304-2838-4273-b6bb-164ffccf33d8" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/ab206350-dfbb-4f36-9a94-97fe94ac447b" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1279, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1339, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1356, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1244, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 545, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/2e89f694-9e42-43dd-b692-9edd444c0176", + "second": "blob:http://127.0.0.1:8084/4885dc4b-93fa-4fea-8ce0-9cda09aef82e", + "created": [ + "blob:http://127.0.0.1:8084/e00fcae6-7c02-418c-8ea8-e10ae764a697", + "blob:http://127.0.0.1:8084/6209c2c1-fcf0-4b43-b5d4-dcec8a101ec2", + "blob:http://127.0.0.1:8084/e8dfdbb6-a8e1-45b2-9081-b57b71b172bb", + "blob:http://127.0.0.1:8084/3f4380fa-22de-477f-ae77-560a21c4aeef", + "blob:http://127.0.0.1:8084/1da7ae36-018c-4fcb-a536-f817103fed30", + "blob:http://127.0.0.1:8084/2ca1aa7e-e8c6-42e9-a759-069c2f1d7239", + "blob:http://127.0.0.1:8084/7a3e40d7-cf7e-4ee4-b1ab-80af8ac402ea", + "blob:http://127.0.0.1:8084/e3ffad8b-8322-4f09-8837-9dab6040489b", + "blob:http://127.0.0.1:8084/7c5578af-5de7-45fe-a3b3-7025559cca51", + "blob:http://127.0.0.1:8084/64e3b34b-50aa-4e3f-98d8-b88fab41c65e", + "blob:http://127.0.0.1:8084/2e89f694-9e42-43dd-b692-9edd444c0176", + "blob:http://127.0.0.1:8084/58483793-e106-4cf1-826b-eed0ced05405", + "blob:http://127.0.0.1:8084/227dc7a5-3a17-490a-9ca1-130814bc041e", + "blob:http://127.0.0.1:8084/9ff0c13f-d6c1-4e03-90f3-6d9a7fdac61e", + "blob:http://127.0.0.1:8084/fcf3219d-ffc6-4d5a-8a92-32241a7a1f51", + "blob:http://127.0.0.1:8084/6ada2459-f4dd-4cbd-b155-ad0bb6e6b6ff", + "blob:http://127.0.0.1:8084/7a9b69d9-47f8-453e-aee0-39e0105a4c29", + "blob:http://127.0.0.1:8084/dedf7a91-bb56-42f8-8e87-427367085a53", + "blob:http://127.0.0.1:8084/8eb0f05e-d582-4ebd-8cb7-9f212ebfc80b", + "blob:http://127.0.0.1:8084/238672e8-2bb3-4a70-844a-44337f2ce3a9", + "blob:http://127.0.0.1:8084/4885dc4b-93fa-4fea-8ce0-9cda09aef82e" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/6209c2c1-fcf0-4b43-b5d4-dcec8a101ec2", + "blob:http://127.0.0.1:8084/e8dfdbb6-a8e1-45b2-9081-b57b71b172bb", + "blob:http://127.0.0.1:8084/3f4380fa-22de-477f-ae77-560a21c4aeef", + "blob:http://127.0.0.1:8084/1da7ae36-018c-4fcb-a536-f817103fed30", + "blob:http://127.0.0.1:8084/2ca1aa7e-e8c6-42e9-a759-069c2f1d7239", + "blob:http://127.0.0.1:8084/7a3e40d7-cf7e-4ee4-b1ab-80af8ac402ea", + "blob:http://127.0.0.1:8084/e3ffad8b-8322-4f09-8837-9dab6040489b", + "blob:http://127.0.0.1:8084/7c5578af-5de7-45fe-a3b3-7025559cca51", + "blob:http://127.0.0.1:8084/64e3b34b-50aa-4e3f-98d8-b88fab41c65e", + "blob:http://127.0.0.1:8084/2e89f694-9e42-43dd-b692-9edd444c0176", + "blob:http://127.0.0.1:8084/58483793-e106-4cf1-826b-eed0ced05405", + "blob:http://127.0.0.1:8084/227dc7a5-3a17-490a-9ca1-130814bc041e", + "blob:http://127.0.0.1:8084/9ff0c13f-d6c1-4e03-90f3-6d9a7fdac61e", + "blob:http://127.0.0.1:8084/fcf3219d-ffc6-4d5a-8a92-32241a7a1f51", + "blob:http://127.0.0.1:8084/6ada2459-f4dd-4cbd-b155-ad0bb6e6b6ff", + "blob:http://127.0.0.1:8084/7a9b69d9-47f8-453e-aee0-39e0105a4c29", + "blob:http://127.0.0.1:8084/dedf7a91-bb56-42f8-8e87-427367085a53", + "blob:http://127.0.0.1:8084/8eb0f05e-d582-4ebd-8cb7-9f212ebfc80b", + "blob:http://127.0.0.1:8084/238672e8-2bb3-4a70-844a-44337f2ce3a9", + "blob:http://127.0.0.1:8084/e00fcae6-7c02-418c-8ea8-e10ae764a697", + "blob:http://127.0.0.1:8084/4885dc4b-93fa-4fea-8ce0-9cda09aef82e" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 187, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 222, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/eded71f5-7e25-4753-8aab-7fddbd1dc050" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/eded71f5-7e25-4753-8aab-7fddbd1dc050", + "blob:http://127.0.0.1:8084/9663e7a3-bccc-4bf7-8825-dfc739145003" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/9663e7a3-bccc-4bf7-8825-dfc739145003" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 348, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/7a967a2b-2015-4626-8d14-c83bf8bf8f9a", + "blob:http://127.0.0.1:8084/6011b29f-8fa5-4e84-85aa-3138af7d2410" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/7a967a2b-2015-4626-8d14-c83bf8bf8f9a" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1587, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38895, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/a01f8463-6363-46c2-a6f4-f4c83fe8f3ee", + "second": "blob:http://127.0.0.1:8084/25724708-4edc-47d9-8a55-1671908b32be", + "created": [ + "blob:http://127.0.0.1:8084/19215587-a6fe-45ca-919c-fdd0e784feb2", + "blob:http://127.0.0.1:8084/09968f39-95e0-4d8c-b569-078a04735e69", + "blob:http://127.0.0.1:8084/bc048413-1250-4cc7-979f-1047fdf0a809", + "blob:http://127.0.0.1:8084/175d8579-8f61-4114-8e22-2c7aa9183eeb", + "blob:http://127.0.0.1:8084/d281c2bb-0296-4f26-929e-df7e60af05b8", + "blob:http://127.0.0.1:8084/39051c07-de09-4517-854a-c0013d2a0719", + "blob:http://127.0.0.1:8084/fd129ef9-ccc0-410d-b1d8-cd764b5f8464", + "blob:http://127.0.0.1:8084/d0bbc23f-2aa9-40e8-bb43-0877b9ff38a5", + "blob:http://127.0.0.1:8084/ece14981-272d-4509-b871-4f47a0a17e1d", + "blob:http://127.0.0.1:8084/dc88b7f5-c738-4b21-a2bd-62d9f230b4e1", + "blob:http://127.0.0.1:8084/a01f8463-6363-46c2-a6f4-f4c83fe8f3ee", + "blob:http://127.0.0.1:8084/9b7fca50-e9e2-4078-84d8-3c54aac080df", + "blob:http://127.0.0.1:8084/b7993466-7676-4ddc-b0f2-18330910f501", + "blob:http://127.0.0.1:8084/d68e2a59-e72b-4d8c-b941-84b02633946b", + "blob:http://127.0.0.1:8084/e5e9955c-f454-4929-9994-296842ace748", + "blob:http://127.0.0.1:8084/f0466d4e-59a2-4d60-8cb8-4ad0a9ef0594", + "blob:http://127.0.0.1:8084/1c809ccd-a4b9-4f96-ade4-9f3c93b37522", + "blob:http://127.0.0.1:8084/0f36e378-5618-4eed-91f7-3ee72ded65bf", + "blob:http://127.0.0.1:8084/e0aa89be-00ef-4936-b4f6-ba3cb547a463", + "blob:http://127.0.0.1:8084/f6a14ea6-4014-46b4-a8bf-1c11bfe0876a", + "blob:http://127.0.0.1:8084/25724708-4edc-47d9-8a55-1671908b32be" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/09968f39-95e0-4d8c-b569-078a04735e69", + "blob:http://127.0.0.1:8084/bc048413-1250-4cc7-979f-1047fdf0a809", + "blob:http://127.0.0.1:8084/175d8579-8f61-4114-8e22-2c7aa9183eeb", + "blob:http://127.0.0.1:8084/d281c2bb-0296-4f26-929e-df7e60af05b8", + "blob:http://127.0.0.1:8084/39051c07-de09-4517-854a-c0013d2a0719", + "blob:http://127.0.0.1:8084/fd129ef9-ccc0-410d-b1d8-cd764b5f8464", + "blob:http://127.0.0.1:8084/d0bbc23f-2aa9-40e8-bb43-0877b9ff38a5", + "blob:http://127.0.0.1:8084/ece14981-272d-4509-b871-4f47a0a17e1d", + "blob:http://127.0.0.1:8084/dc88b7f5-c738-4b21-a2bd-62d9f230b4e1", + "blob:http://127.0.0.1:8084/a01f8463-6363-46c2-a6f4-f4c83fe8f3ee", + "blob:http://127.0.0.1:8084/9b7fca50-e9e2-4078-84d8-3c54aac080df", + "blob:http://127.0.0.1:8084/b7993466-7676-4ddc-b0f2-18330910f501", + "blob:http://127.0.0.1:8084/d68e2a59-e72b-4d8c-b941-84b02633946b", + "blob:http://127.0.0.1:8084/e5e9955c-f454-4929-9994-296842ace748", + "blob:http://127.0.0.1:8084/f0466d4e-59a2-4d60-8cb8-4ad0a9ef0594", + "blob:http://127.0.0.1:8084/1c809ccd-a4b9-4f96-ade4-9f3c93b37522", + "blob:http://127.0.0.1:8084/0f36e378-5618-4eed-91f7-3ee72ded65bf", + "blob:http://127.0.0.1:8084/e0aa89be-00ef-4936-b4f6-ba3cb547a463", + "blob:http://127.0.0.1:8084/f6a14ea6-4014-46b4-a8bf-1c11bfe0876a", + "blob:http://127.0.0.1:8084/19215587-a6fe-45ca-919c-fdd0e784feb2", + "blob:http://127.0.0.1:8084/25724708-4edc-47d9-8a55-1671908b32be" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 427, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 571, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/d384b82a-66ce-4d40-86b3-bdfe526051eb" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/d384b82a-66ce-4d40-86b3-bdfe526051eb", + "blob:http://127.0.0.1:8084/4e332ad2-34d5-400a-9415-a549a2a2b551" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/4e332ad2-34d5-400a-9415-a549a2a2b551" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 568, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/fe252f9a-e978-4306-80a3-7d436c495ae8", + "blob:http://127.0.0.1:8084/1963e817-7f7b-43f2-a602-714aa1acda3e" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/fe252f9a-e978-4306-80a3-7d436c495ae8" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1280, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1293, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1244, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1328, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 589, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/64cd9cf3-c7c0-4ada-941d-def17950ede1", + "second": "blob:http://127.0.0.1:8084/6f43459f-075f-43e5-b8fe-bc621b5de53e", + "created": [ + "blob:http://127.0.0.1:8084/e83b863f-23a8-4b4a-9f40-02f181e7620e", + "blob:http://127.0.0.1:8084/e27ac478-7bff-4e94-9ee1-902d11915849", + "blob:http://127.0.0.1:8084/8992468c-9187-43dc-9ea9-30f16a17b9b8", + "blob:http://127.0.0.1:8084/4a30519a-3c62-456c-9152-3e451308ae6e", + "blob:http://127.0.0.1:8084/e381b8bd-f24f-491b-b5fe-52690840aac9", + "blob:http://127.0.0.1:8084/1d88e87d-b916-4bea-b796-64180878187f", + "blob:http://127.0.0.1:8084/12d971be-44d5-41a9-ad36-ef705047c49f", + "blob:http://127.0.0.1:8084/70062c71-f5aa-4caa-8fab-df2694eb1dc0", + "blob:http://127.0.0.1:8084/01fbab78-0dc5-4f3f-9770-1806cf409cda", + "blob:http://127.0.0.1:8084/90f9a4aa-d2a5-4a58-98a1-c4e48738442f", + "blob:http://127.0.0.1:8084/64cd9cf3-c7c0-4ada-941d-def17950ede1", + "blob:http://127.0.0.1:8084/4cc4024d-0c68-4536-aba9-f1d75ff7fafa", + "blob:http://127.0.0.1:8084/c9ac706a-e2b1-421c-9710-bf9caaa6f32c", + "blob:http://127.0.0.1:8084/7c380cb4-7936-456e-8454-742598b3c5a4", + "blob:http://127.0.0.1:8084/e8f216b1-22c1-426b-a86c-2065a268c649", + "blob:http://127.0.0.1:8084/e26422c4-04b4-449b-8842-59623fd9c0ec", + "blob:http://127.0.0.1:8084/fc9eb7af-8936-4a7e-859a-b7e96c5751b7", + "blob:http://127.0.0.1:8084/f3ebaba8-8fd9-4aef-80e8-69402ed3bafa", + "blob:http://127.0.0.1:8084/eaa34c47-dd0f-4e96-8b50-524052672ef3", + "blob:http://127.0.0.1:8084/fa027cf2-2b1f-4c99-87ce-484292c335d4", + "blob:http://127.0.0.1:8084/6f43459f-075f-43e5-b8fe-bc621b5de53e" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/e27ac478-7bff-4e94-9ee1-902d11915849", + "blob:http://127.0.0.1:8084/8992468c-9187-43dc-9ea9-30f16a17b9b8", + "blob:http://127.0.0.1:8084/4a30519a-3c62-456c-9152-3e451308ae6e", + "blob:http://127.0.0.1:8084/e381b8bd-f24f-491b-b5fe-52690840aac9", + "blob:http://127.0.0.1:8084/1d88e87d-b916-4bea-b796-64180878187f", + "blob:http://127.0.0.1:8084/12d971be-44d5-41a9-ad36-ef705047c49f", + "blob:http://127.0.0.1:8084/70062c71-f5aa-4caa-8fab-df2694eb1dc0", + "blob:http://127.0.0.1:8084/01fbab78-0dc5-4f3f-9770-1806cf409cda", + "blob:http://127.0.0.1:8084/90f9a4aa-d2a5-4a58-98a1-c4e48738442f", + "blob:http://127.0.0.1:8084/64cd9cf3-c7c0-4ada-941d-def17950ede1", + "blob:http://127.0.0.1:8084/4cc4024d-0c68-4536-aba9-f1d75ff7fafa", + "blob:http://127.0.0.1:8084/c9ac706a-e2b1-421c-9710-bf9caaa6f32c", + "blob:http://127.0.0.1:8084/7c380cb4-7936-456e-8454-742598b3c5a4", + "blob:http://127.0.0.1:8084/e8f216b1-22c1-426b-a86c-2065a268c649", + "blob:http://127.0.0.1:8084/e26422c4-04b4-449b-8842-59623fd9c0ec", + "blob:http://127.0.0.1:8084/fc9eb7af-8936-4a7e-859a-b7e96c5751b7", + "blob:http://127.0.0.1:8084/f3ebaba8-8fd9-4aef-80e8-69402ed3bafa", + "blob:http://127.0.0.1:8084/eaa34c47-dd0f-4e96-8b50-524052672ef3", + "blob:http://127.0.0.1:8084/fa027cf2-2b1f-4c99-87ce-484292c335d4", + "blob:http://127.0.0.1:8084/e83b863f-23a8-4b4a-9f40-02f181e7620e", + "blob:http://127.0.0.1:8084/6f43459f-075f-43e5-b8fe-bc621b5de53e" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 174, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 232, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/431b3005-7af2-4020-bef9-1ca9e72cbd0b" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/431b3005-7af2-4020-bef9-1ca9e72cbd0b", + "blob:http://127.0.0.1:8084/c0b37344-baf0-4c2e-8205-8ca9cbe3b379" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/c0b37344-baf0-4c2e-8205-8ca9cbe3b379" + ] + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 340, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/8d78a906-1d47-4f28-9f7b-9ec5cb960276", + "blob:http://127.0.0.1:8084/1349020a-e794-42a5-b309-130871dbcbbe" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/8d78a906-1d47-4f28-9f7b-9ec5cb960276" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1578, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38895, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/368ab090-e674-497b-8770-b21efdbbabea", + "second": "blob:http://127.0.0.1:8084/3048f6b7-e867-4116-9457-b60e7335f814", + "created": [ + "blob:http://127.0.0.1:8084/f9507fce-4c0e-4687-af0b-55d6927ed2d6", + "blob:http://127.0.0.1:8084/efc4c375-a7c4-4a84-a524-482c00820717", + "blob:http://127.0.0.1:8084/5a1f62d8-3a3b-4663-86ea-808e52ea2902", + "blob:http://127.0.0.1:8084/4c3c9745-3c77-4950-bee9-8e226c680c88", + "blob:http://127.0.0.1:8084/b246b312-c0a1-43dd-a2d3-18043feaac94", + "blob:http://127.0.0.1:8084/791a55aa-9a2b-469b-897f-ed727e9f24a9", + "blob:http://127.0.0.1:8084/05bfc21c-0cde-4856-a0c7-61de532d7167", + "blob:http://127.0.0.1:8084/fd9f0fa3-3901-44b9-9760-480718845265", + "blob:http://127.0.0.1:8084/7222b3aa-f3b7-4a39-9b24-3e3793015c2d", + "blob:http://127.0.0.1:8084/bdfe29fa-15f9-46e1-be3f-e4e5dd38483f", + "blob:http://127.0.0.1:8084/368ab090-e674-497b-8770-b21efdbbabea", + "blob:http://127.0.0.1:8084/ad1c81f2-e30b-4627-897f-3865c7912d0f", + "blob:http://127.0.0.1:8084/2b654d36-6f32-4b07-8dc5-e597b0c658d5", + "blob:http://127.0.0.1:8084/1dc5821f-7347-422b-93c5-6b273ef890f1", + "blob:http://127.0.0.1:8084/10ff74f7-ab62-4cda-a492-52ecd150f4ce", + "blob:http://127.0.0.1:8084/53b8cc0b-1bb8-4acd-847d-2eabe23fbcce", + "blob:http://127.0.0.1:8084/4e5f9eb0-f007-4609-b015-13416b3bd9ce", + "blob:http://127.0.0.1:8084/82b7b749-b0fa-4c43-9812-29c7e5af8461", + "blob:http://127.0.0.1:8084/4ff4ae62-c88a-44bd-a9ba-282179088602", + "blob:http://127.0.0.1:8084/58144089-6712-4aab-87b4-05aef09e972c", + "blob:http://127.0.0.1:8084/3048f6b7-e867-4116-9457-b60e7335f814" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/efc4c375-a7c4-4a84-a524-482c00820717", + "blob:http://127.0.0.1:8084/5a1f62d8-3a3b-4663-86ea-808e52ea2902", + "blob:http://127.0.0.1:8084/4c3c9745-3c77-4950-bee9-8e226c680c88", + "blob:http://127.0.0.1:8084/b246b312-c0a1-43dd-a2d3-18043feaac94", + "blob:http://127.0.0.1:8084/791a55aa-9a2b-469b-897f-ed727e9f24a9", + "blob:http://127.0.0.1:8084/05bfc21c-0cde-4856-a0c7-61de532d7167", + "blob:http://127.0.0.1:8084/fd9f0fa3-3901-44b9-9760-480718845265", + "blob:http://127.0.0.1:8084/7222b3aa-f3b7-4a39-9b24-3e3793015c2d", + "blob:http://127.0.0.1:8084/bdfe29fa-15f9-46e1-be3f-e4e5dd38483f", + "blob:http://127.0.0.1:8084/368ab090-e674-497b-8770-b21efdbbabea", + "blob:http://127.0.0.1:8084/ad1c81f2-e30b-4627-897f-3865c7912d0f", + "blob:http://127.0.0.1:8084/2b654d36-6f32-4b07-8dc5-e597b0c658d5", + "blob:http://127.0.0.1:8084/1dc5821f-7347-422b-93c5-6b273ef890f1", + "blob:http://127.0.0.1:8084/10ff74f7-ab62-4cda-a492-52ecd150f4ce", + "blob:http://127.0.0.1:8084/53b8cc0b-1bb8-4acd-847d-2eabe23fbcce", + "blob:http://127.0.0.1:8084/4e5f9eb0-f007-4609-b015-13416b3bd9ce", + "blob:http://127.0.0.1:8084/82b7b749-b0fa-4c43-9812-29c7e5af8461", + "blob:http://127.0.0.1:8084/4ff4ae62-c88a-44bd-a9ba-282179088602", + "blob:http://127.0.0.1:8084/58144089-6712-4aab-87b4-05aef09e972c", + "blob:http://127.0.0.1:8084/f9507fce-4c0e-4687-af0b-55d6927ed2d6", + "blob:http://127.0.0.1:8084/3048f6b7-e867-4116-9457-b60e7335f814" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 489, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 612, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/9f9fc684-4144-433c-9df2-5ab08ea2435f" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/9f9fc684-4144-433c-9df2-5ab08ea2435f", + "blob:http://127.0.0.1:8084/989243cc-41d6-454a-bfef-c8df7c996844" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/989243cc-41d6-454a-bfef-c8df7c996844" + ] + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1493, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/a065b7dc-eb5a-46df-b493-e2b27cb406ca", + "blob:http://127.0.0.1:8084/9fed0e38-e73f-4e09-bab7-fb94263821be" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/a065b7dc-eb5a-46df-b493-e2b27cb406ca" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1324, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1297, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1268, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1246, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + } + ] + }, + { + "variant": "legacy", + "counts": { + "candidate-native-input": 3, + "native-media-control": 3, + "blob-unavailable-control": 16, + "actual-tool-scenario": 32 + }, + "cases": [ + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "chromium", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 275, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "firefox", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 1785, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-input.spec.js / Thumbnail input ownership replaces real DOM listeners and generated inputs", + "project": "webkit", + "kind": "candidate-native-input", + "status": "passed", + "retry": 0, + "durationMs": 785, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-input-ownership", + "data": { + "implementation": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "scope": "Native file input/DOM/listeners only; does not claim media decoding.", + "switched": { + "value": "", + "events": [ + "thumbnail-pattern.mp4" + ], + "firstPosition": "sticky", + "disconnected": true + }, + "result": { + "events": [ + "thumbnail-pattern.mp4", + "thumbnail-pattern.mp4" + ], + "sameError": true, + "notifications": 1, + "inputConnected": false, + "videoConnected": false, + "secondPosition": "absolute", + "inputs": 0 + } + } + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "chromium", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 252, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.046009, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.046009, + "width": 640 + } + ] + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "firefox", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 1985, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.045986, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "loaded", + "readyState": 4, + "error": 0, + "duration": 90.045986, + "width": 640 + } + ] + } + ] + }, + { + "title": "thumbnail-native.spec.js / Thumbnail native HTTP and Blob media controls", + "project": "webkit", + "kind": "native-media-control", + "status": "passed", + "retry": 0, + "durationMs": 2854, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-native-media-controls", + "data": [ + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 3, + "error": 0, + "duration": 8, + "width": 320 + }, + { + "url": "/test/pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 3, + "error": 0, + "duration": 24, + "width": 320 + }, + { + "url": "/test/thumbnail-pattern.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "http", + "outcome": "loaded", + "readyState": 2, + "error": 0, + "duration": 90.094, + "width": 640 + }, + { + "url": "/assets/sample/video.mp4", + "type": "video/mp4", + "transport": "blob", + "outcome": "error", + "readyState": 0, + "error": 4, + "duration": null, + "width": 0 + } + ] + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 8143, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 150, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 30, + "mime": "image/png", + "bytes": 26427, + "nonBlack": 2400, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/4053061c-3cae-498a-ac5a-af053a9540ef", + "second": "blob:http://127.0.0.1:8084/5fbf3741-7d73-43f4-b558-f79cc0cb24ef", + "created": [ + "blob:http://127.0.0.1:8084/77723614-0681-4f07-a15d-98f0cd692b11", + "blob:http://127.0.0.1:8084/eec1f8a4-a279-48b6-a61c-63908074df40", + "blob:http://127.0.0.1:8084/9f5f4aa8-f69a-4781-b216-48df9f7a9839", + "blob:http://127.0.0.1:8084/7e7d5944-9b17-4112-b2df-0c219ab54d31", + "blob:http://127.0.0.1:8084/85e52d2e-f279-4b51-90a3-1bff4dba8a22", + "blob:http://127.0.0.1:8084/2b44e6bf-420d-4e95-91b7-0c826bd7a10a", + "blob:http://127.0.0.1:8084/06426684-535a-483c-8b3e-1be9659a4651", + "blob:http://127.0.0.1:8084/e03ed51b-ad07-4e82-a356-112d63c8b1a0", + "blob:http://127.0.0.1:8084/202f8558-24c7-46be-8cb7-6e508afead82", + "blob:http://127.0.0.1:8084/b1999513-cae4-409b-b068-d6e7bb564abf", + "blob:http://127.0.0.1:8084/4053061c-3cae-498a-ac5a-af053a9540ef", + "blob:http://127.0.0.1:8084/061ef457-c6d8-43a8-a772-8f59f94e446c", + "blob:http://127.0.0.1:8084/d1007b11-3793-4fd2-93d7-06bce7149468", + "blob:http://127.0.0.1:8084/47f5f74d-828d-4c43-9207-1ccf3406e983", + "blob:http://127.0.0.1:8084/a8e816c1-0ac7-457a-9d89-9037050a9b38", + "blob:http://127.0.0.1:8084/1e767726-48d8-4f4b-a8f9-479e940a350f", + "blob:http://127.0.0.1:8084/324c0445-30ff-41aa-a408-7d252c6c5c90", + "blob:http://127.0.0.1:8084/c458437e-db20-422b-ae5b-bbece0e652ae", + "blob:http://127.0.0.1:8084/20045ae4-db15-4325-9fd9-6e00de4f3a8a", + "blob:http://127.0.0.1:8084/0a4bbc7d-5941-4602-95f5-7c65b64590ae", + "blob:http://127.0.0.1:8084/5fbf3741-7d73-43f4-b558-f79cc0cb24ef" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/eec1f8a4-a279-48b6-a61c-63908074df40", + "blob:http://127.0.0.1:8084/9f5f4aa8-f69a-4781-b216-48df9f7a9839", + "blob:http://127.0.0.1:8084/7e7d5944-9b17-4112-b2df-0c219ab54d31", + "blob:http://127.0.0.1:8084/85e52d2e-f279-4b51-90a3-1bff4dba8a22", + "blob:http://127.0.0.1:8084/2b44e6bf-420d-4e95-91b7-0c826bd7a10a", + "blob:http://127.0.0.1:8084/06426684-535a-483c-8b3e-1be9659a4651", + "blob:http://127.0.0.1:8084/e03ed51b-ad07-4e82-a356-112d63c8b1a0", + "blob:http://127.0.0.1:8084/202f8558-24c7-46be-8cb7-6e508afead82", + "blob:http://127.0.0.1:8084/b1999513-cae4-409b-b068-d6e7bb564abf", + "blob:http://127.0.0.1:8084/4053061c-3cae-498a-ac5a-af053a9540ef", + "blob:http://127.0.0.1:8084/061ef457-c6d8-43a8-a772-8f59f94e446c", + "blob:http://127.0.0.1:8084/d1007b11-3793-4fd2-93d7-06bce7149468", + "blob:http://127.0.0.1:8084/47f5f74d-828d-4c43-9207-1ccf3406e983", + "blob:http://127.0.0.1:8084/a8e816c1-0ac7-457a-9d89-9037050a9b38", + "blob:http://127.0.0.1:8084/1e767726-48d8-4f4b-a8f9-479e940a350f", + "blob:http://127.0.0.1:8084/324c0445-30ff-41aa-a408-7d252c6c5c90", + "blob:http://127.0.0.1:8084/c458437e-db20-422b-ae5b-bbece0e652ae", + "blob:http://127.0.0.1:8084/20045ae4-db15-4325-9fd9-6e00de4f3a8a", + "blob:http://127.0.0.1:8084/0a4bbc7d-5941-4602-95f5-7c65b64590ae", + "blob:http://127.0.0.1:8084/77723614-0681-4f07-a15d-98f0cd692b11", + "blob:http://127.0.0.1:8084/5fbf3741-7d73-43f4-b558-f79cc0cb24ef" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 230, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 253, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/639a6f78-f4c1-4b5d-97fe-883a708349ab" + }, + "result": { + "value": "C:\\fakepath\\thumbnail-pattern.mp4", + "created": [ + "blob:http://127.0.0.1:8084/639a6f78-f4c1-4b5d-97fe-883a708349ab", + "blob:http://127.0.0.1:8084/8e07e68c-a492-4e90-b4b8-7e5460fdec93" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/8e07e68c-a492-4e90-b4b8-7e5460fdec93" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 614, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/18f4f9b1-f291-45f5-8b48-7d39bd6b4e14", + "blob:http://127.0.0.1:8084/30fbe1e3-dade-417f-a9c3-2538604112b2" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/18f4f9b1-f291-45f5-8b48-7d39bd6b4e14" + ], + "pendingState": "pending", + "events": [ + "file", + "canvas", + "video", + "destroy", + "update" + ], + "connected": false, + "bytes": 7540 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 8535, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 150, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 30, + "mime": "image/png", + "bytes": 20020, + "nonBlack": 2400, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/b9d84c98-4e26-4d16-a209-7a8252387de1", + "second": "blob:http://127.0.0.1:8084/0dcdc2ca-bd9a-492f-b1ed-811f7a25df72", + "created": [ + "blob:http://127.0.0.1:8084/08e08ba5-b419-4aaa-8dbf-182c4f956794", + "blob:http://127.0.0.1:8084/10fca677-827f-4c75-8d17-1b77d22f969c", + "blob:http://127.0.0.1:8084/14e01bfd-4673-4940-b626-dd64252802c0", + "blob:http://127.0.0.1:8084/c1000f05-0542-4d1b-8a2c-1c759fca519a", + "blob:http://127.0.0.1:8084/0455d5f2-bccf-450a-b93e-29e9dea915f9", + "blob:http://127.0.0.1:8084/829f5e56-7842-4c81-8775-18364d00b6ca", + "blob:http://127.0.0.1:8084/cfa5a557-ec2f-4aca-9a19-9a32380458b9", + "blob:http://127.0.0.1:8084/f6ccf12e-0aed-4290-9514-b4d3493d4ee3", + "blob:http://127.0.0.1:8084/df95ed9d-2071-4a52-8f15-e960fc810e2c", + "blob:http://127.0.0.1:8084/7cb66452-a4b3-49e6-a1d0-452c44bcd6b4", + "blob:http://127.0.0.1:8084/b9d84c98-4e26-4d16-a209-7a8252387de1", + "blob:http://127.0.0.1:8084/04336a48-7fc3-4be6-990d-5426624bc7dc", + "blob:http://127.0.0.1:8084/370ed7e3-503a-4a3d-b9b6-3507ff9d55b1", + "blob:http://127.0.0.1:8084/44f0bedf-adca-4ea2-ae0d-787b9f48d5dc", + "blob:http://127.0.0.1:8084/245cc247-1635-403d-954b-c9ab2f117901", + "blob:http://127.0.0.1:8084/d1cb3ab1-4658-4113-96b5-f3e8b8da652d", + "blob:http://127.0.0.1:8084/0ed0536f-ddb5-4cc1-950e-25a6602354c6", + "blob:http://127.0.0.1:8084/0e69bdeb-8a4e-41b0-b3f1-e6aae0432f82", + "blob:http://127.0.0.1:8084/dd0356ca-5a4c-4563-8a23-1264910ba1a7", + "blob:http://127.0.0.1:8084/e6dd2249-63cc-4a87-a928-99474556a9fd", + "blob:http://127.0.0.1:8084/0dcdc2ca-bd9a-492f-b1ed-811f7a25df72" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/10fca677-827f-4c75-8d17-1b77d22f969c", + "blob:http://127.0.0.1:8084/14e01bfd-4673-4940-b626-dd64252802c0", + "blob:http://127.0.0.1:8084/c1000f05-0542-4d1b-8a2c-1c759fca519a", + "blob:http://127.0.0.1:8084/0455d5f2-bccf-450a-b93e-29e9dea915f9", + "blob:http://127.0.0.1:8084/829f5e56-7842-4c81-8775-18364d00b6ca", + "blob:http://127.0.0.1:8084/cfa5a557-ec2f-4aca-9a19-9a32380458b9", + "blob:http://127.0.0.1:8084/f6ccf12e-0aed-4290-9514-b4d3493d4ee3", + "blob:http://127.0.0.1:8084/df95ed9d-2071-4a52-8f15-e960fc810e2c", + "blob:http://127.0.0.1:8084/7cb66452-a4b3-49e6-a1d0-452c44bcd6b4", + "blob:http://127.0.0.1:8084/b9d84c98-4e26-4d16-a209-7a8252387de1", + "blob:http://127.0.0.1:8084/04336a48-7fc3-4be6-990d-5426624bc7dc", + "blob:http://127.0.0.1:8084/370ed7e3-503a-4a3d-b9b6-3507ff9d55b1", + "blob:http://127.0.0.1:8084/44f0bedf-adca-4ea2-ae0d-787b9f48d5dc", + "blob:http://127.0.0.1:8084/245cc247-1635-403d-954b-c9ab2f117901", + "blob:http://127.0.0.1:8084/d1cb3ab1-4658-4113-96b5-f3e8b8da652d", + "blob:http://127.0.0.1:8084/0ed0536f-ddb5-4cc1-950e-25a6602354c6", + "blob:http://127.0.0.1:8084/0e69bdeb-8a4e-41b0-b3f1-e6aae0432f82", + "blob:http://127.0.0.1:8084/dd0356ca-5a4c-4563-8a23-1264910ba1a7", + "blob:http://127.0.0.1:8084/e6dd2249-63cc-4a87-a928-99474556a9fd", + "blob:http://127.0.0.1:8084/08e08ba5-b419-4aaa-8dbf-182c4f956794", + "blob:http://127.0.0.1:8084/0dcdc2ca-bd9a-492f-b1ed-811f7a25df72" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 474, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 495, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/23416d47-2687-453b-8870-7e076f70d7a8" + }, + "result": { + "value": "C:\\fakepath\\thumbnail-pattern.mp4", + "created": [ + "blob:http://127.0.0.1:8084/23416d47-2687-453b-8870-7e076f70d7a8", + "blob:http://127.0.0.1:8084/9ad01667-bd22-47dd-b113-6a704e206afa" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/9ad01667-bd22-47dd-b113-6a704e206afa" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1808, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/37375969-01b4-4f46-9979-cc94f2772d8f", + "blob:http://127.0.0.1:8084/b0c71099-240b-410f-aa5a-5882b41cae16" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/37375969-01b4-4f46-9979-cc94f2772d8f" + ], + "pendingState": "pending", + "events": [ + "file", + "canvas", + "video", + "destroy", + "update" + ], + "connected": false, + "bytes": 4980 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1495, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1354, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1407, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool cdn-3.5.31 / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1353, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "cdn-3.5.31", + "sha256": "27fdc506c9b228c40df39f8508b3a42c145571c06c0b9cc60327a007a2064c87", + "recoveredIndividualFile": true, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 483, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/ea9714d6-a1d0-4be5-ae62-c7aa8c0f7d0b", + "second": "blob:http://127.0.0.1:8084/78adc1d6-446b-4c98-9385-d1ea6a930150", + "created": [ + "blob:http://127.0.0.1:8084/021e9ce2-c942-4dcb-9d3f-8027a9a5de74", + "blob:http://127.0.0.1:8084/618a711d-33b7-4441-9722-4b5f1f8c203c", + "blob:http://127.0.0.1:8084/890fc89f-dfde-4df9-9e9c-998641fa4900", + "blob:http://127.0.0.1:8084/e3143339-c4c7-4c7c-981c-31cd81a89edf", + "blob:http://127.0.0.1:8084/e21a90a2-d9db-4c78-b36b-37cad2541e81", + "blob:http://127.0.0.1:8084/fef8ac51-d34e-4d38-8d47-6d17b54533da", + "blob:http://127.0.0.1:8084/e6169c96-1fa0-405b-864a-807c837cd74b", + "blob:http://127.0.0.1:8084/92894ce9-bbb2-48ba-befc-dc2db6f740dc", + "blob:http://127.0.0.1:8084/40d0a2bf-b070-49c0-9f77-9023e5ca63ff", + "blob:http://127.0.0.1:8084/095d9140-c382-49e1-8cda-14f875869dfe", + "blob:http://127.0.0.1:8084/ea9714d6-a1d0-4be5-ae62-c7aa8c0f7d0b", + "blob:http://127.0.0.1:8084/bc8ca9f5-b76c-483f-9018-702f9edc760a", + "blob:http://127.0.0.1:8084/40ef8177-a5d3-488e-8486-a71a245979f1", + "blob:http://127.0.0.1:8084/3554fbd0-c4f8-4dd2-aa0c-9b100b18c648", + "blob:http://127.0.0.1:8084/fe06f30f-16f0-463c-b828-927956ba4993", + "blob:http://127.0.0.1:8084/8928ec38-5ce7-4a37-839e-05c3a971e512", + "blob:http://127.0.0.1:8084/1434d423-ff93-4e88-949f-b60c268a90c7", + "blob:http://127.0.0.1:8084/5dbcff6e-67e8-4b97-93f8-918260232b81", + "blob:http://127.0.0.1:8084/f9375af7-778d-4972-be46-53cf4c3bebb7", + "blob:http://127.0.0.1:8084/9549ddb6-1adf-445b-aa16-0a126770bb54", + "blob:http://127.0.0.1:8084/78adc1d6-446b-4c98-9385-d1ea6a930150" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/618a711d-33b7-4441-9722-4b5f1f8c203c", + "blob:http://127.0.0.1:8084/890fc89f-dfde-4df9-9e9c-998641fa4900", + "blob:http://127.0.0.1:8084/e3143339-c4c7-4c7c-981c-31cd81a89edf", + "blob:http://127.0.0.1:8084/e21a90a2-d9db-4c78-b36b-37cad2541e81", + "blob:http://127.0.0.1:8084/fef8ac51-d34e-4d38-8d47-6d17b54533da", + "blob:http://127.0.0.1:8084/e6169c96-1fa0-405b-864a-807c837cd74b", + "blob:http://127.0.0.1:8084/92894ce9-bbb2-48ba-befc-dc2db6f740dc", + "blob:http://127.0.0.1:8084/40d0a2bf-b070-49c0-9f77-9023e5ca63ff", + "blob:http://127.0.0.1:8084/095d9140-c382-49e1-8cda-14f875869dfe", + "blob:http://127.0.0.1:8084/ea9714d6-a1d0-4be5-ae62-c7aa8c0f7d0b", + "blob:http://127.0.0.1:8084/bc8ca9f5-b76c-483f-9018-702f9edc760a", + "blob:http://127.0.0.1:8084/40ef8177-a5d3-488e-8486-a71a245979f1", + "blob:http://127.0.0.1:8084/3554fbd0-c4f8-4dd2-aa0c-9b100b18c648", + "blob:http://127.0.0.1:8084/fe06f30f-16f0-463c-b828-927956ba4993", + "blob:http://127.0.0.1:8084/8928ec38-5ce7-4a37-839e-05c3a971e512", + "blob:http://127.0.0.1:8084/1434d423-ff93-4e88-949f-b60c268a90c7", + "blob:http://127.0.0.1:8084/5dbcff6e-67e8-4b97-93f8-918260232b81", + "blob:http://127.0.0.1:8084/f9375af7-778d-4972-be46-53cf4c3bebb7", + "blob:http://127.0.0.1:8084/9549ddb6-1adf-445b-aa16-0a126770bb54", + "blob:http://127.0.0.1:8084/021e9ce2-c942-4dcb-9d3f-8027a9a5de74", + "blob:http://127.0.0.1:8084/78adc1d6-446b-4c98-9385-d1ea6a930150" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 210, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 249, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/fd41ec04-3d4f-4f9f-98ef-a89e455e48c2" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/fd41ec04-3d4f-4f9f-98ef-a89e455e48c2", + "blob:http://127.0.0.1:8084/e5ef3608-22c0-40a6-8561-43e16afd956c" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/e5ef3608-22c0-40a6-8561-43e16afd956c" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 353, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/fb64ce8e-6da8-4da3-90ec-a035c4c9cdc0", + "blob:http://127.0.0.1:8084/ae35e9b9-0aa5-4009-89f2-0717d580d456" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/fb64ce8e-6da8-4da3-90ec-a035c4c9cdc0" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1588, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38895, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/125412f8-c960-4c8e-9aee-eb77470b0fe2", + "second": "blob:http://127.0.0.1:8084/e5fb613c-f2b6-4265-bb89-74750c708c60", + "created": [ + "blob:http://127.0.0.1:8084/ad2858be-9fcc-4d7d-92de-9fa4425f5240", + "blob:http://127.0.0.1:8084/71c6aae2-2ae7-4f43-9b9a-d1c36de8b07a", + "blob:http://127.0.0.1:8084/662d6be8-ccea-4082-9282-127db56cff89", + "blob:http://127.0.0.1:8084/32d6732d-fffa-43e2-bd33-7a97e37f29d2", + "blob:http://127.0.0.1:8084/256fabf6-0cfd-4ffa-8f1f-3f7e6c4dadf9", + "blob:http://127.0.0.1:8084/afa0f2b2-92fe-4dc1-8422-9bf3b995a573", + "blob:http://127.0.0.1:8084/e9ad54b9-df3f-4792-908a-eac31f365b3b", + "blob:http://127.0.0.1:8084/d09d14ed-83e2-4e81-9291-5db895b7616c", + "blob:http://127.0.0.1:8084/6110b5ed-3d8b-4d21-bf45-7b9b19247aef", + "blob:http://127.0.0.1:8084/c1c164a9-a626-49c5-8053-f2f294a8aa2d", + "blob:http://127.0.0.1:8084/125412f8-c960-4c8e-9aee-eb77470b0fe2", + "blob:http://127.0.0.1:8084/2851d2f6-f52c-462f-93d1-d77086895d18", + "blob:http://127.0.0.1:8084/b650e272-58ae-4b1c-bdf7-4a236ec85c7c", + "blob:http://127.0.0.1:8084/ec73bc65-cf0b-46a9-84b8-8955b5a775a6", + "blob:http://127.0.0.1:8084/aac38e4b-f94c-405b-b568-fa0b34969a02", + "blob:http://127.0.0.1:8084/33b1634b-0cd5-47e5-b5ae-e24350394cb7", + "blob:http://127.0.0.1:8084/16f9e4f4-b9ed-4cc1-863a-1a0d3f2dd1bf", + "blob:http://127.0.0.1:8084/28795d19-f06b-4752-8e13-0778f59a47ad", + "blob:http://127.0.0.1:8084/88eae624-a846-4100-9dd5-77f8601f607a", + "blob:http://127.0.0.1:8084/79bf797c-f3ee-4911-aeee-039635a2e8ae", + "blob:http://127.0.0.1:8084/e5fb613c-f2b6-4265-bb89-74750c708c60" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/71c6aae2-2ae7-4f43-9b9a-d1c36de8b07a", + "blob:http://127.0.0.1:8084/662d6be8-ccea-4082-9282-127db56cff89", + "blob:http://127.0.0.1:8084/32d6732d-fffa-43e2-bd33-7a97e37f29d2", + "blob:http://127.0.0.1:8084/256fabf6-0cfd-4ffa-8f1f-3f7e6c4dadf9", + "blob:http://127.0.0.1:8084/afa0f2b2-92fe-4dc1-8422-9bf3b995a573", + "blob:http://127.0.0.1:8084/e9ad54b9-df3f-4792-908a-eac31f365b3b", + "blob:http://127.0.0.1:8084/d09d14ed-83e2-4e81-9291-5db895b7616c", + "blob:http://127.0.0.1:8084/6110b5ed-3d8b-4d21-bf45-7b9b19247aef", + "blob:http://127.0.0.1:8084/c1c164a9-a626-49c5-8053-f2f294a8aa2d", + "blob:http://127.0.0.1:8084/125412f8-c960-4c8e-9aee-eb77470b0fe2", + "blob:http://127.0.0.1:8084/2851d2f6-f52c-462f-93d1-d77086895d18", + "blob:http://127.0.0.1:8084/b650e272-58ae-4b1c-bdf7-4a236ec85c7c", + "blob:http://127.0.0.1:8084/ec73bc65-cf0b-46a9-84b8-8955b5a775a6", + "blob:http://127.0.0.1:8084/aac38e4b-f94c-405b-b568-fa0b34969a02", + "blob:http://127.0.0.1:8084/33b1634b-0cd5-47e5-b5ae-e24350394cb7", + "blob:http://127.0.0.1:8084/16f9e4f4-b9ed-4cc1-863a-1a0d3f2dd1bf", + "blob:http://127.0.0.1:8084/28795d19-f06b-4752-8e13-0778f59a47ad", + "blob:http://127.0.0.1:8084/88eae624-a846-4100-9dd5-77f8601f607a", + "blob:http://127.0.0.1:8084/79bf797c-f3ee-4911-aeee-039635a2e8ae", + "blob:http://127.0.0.1:8084/ad2858be-9fcc-4d7d-92de-9fa4425f5240", + "blob:http://127.0.0.1:8084/e5fb613c-f2b6-4265-bb89-74750c708c60" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 421, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 570, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/8c81508a-3111-4608-9cda-6e78c1d744a1" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/8c81508a-3111-4608-9cda-6e78c1d744a1", + "blob:http://127.0.0.1:8084/d528df1a-b922-4b0e-a269-8bf8187d3ab4" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/d528df1a-b922-4b0e-a269-8bf8187d3ab4" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 800, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/b74f3c23-c868-4e52-a2d6-2b40461ed840", + "blob:http://127.0.0.1:8084/6690a107-a6b8-4444-bdd2-60954721a0ea" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/b74f3c23-c868-4e52-a2d6-2b40461ed840" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1364, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1373, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1369, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1312, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 540, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/f13d2f21-4180-4394-a4f3-cdf0568e06ee", + "second": "blob:http://127.0.0.1:8084/d5222f86-8bda-4a6f-ba92-231130195312", + "created": [ + "blob:http://127.0.0.1:8084/31ab8dd6-96eb-4b74-aea7-cb15f945ec03", + "blob:http://127.0.0.1:8084/e9607d3b-cd9e-43d3-b79f-1cbf8980a94b", + "blob:http://127.0.0.1:8084/b323c86b-4b45-43a9-a167-6c5143719e60", + "blob:http://127.0.0.1:8084/447d1bed-ab23-4374-9f20-73e225e2a85b", + "blob:http://127.0.0.1:8084/562e128a-e521-43ed-90f6-72732c55dee5", + "blob:http://127.0.0.1:8084/6b22b7c0-adff-4c3e-9cf9-10cee649e3c0", + "blob:http://127.0.0.1:8084/8832a0c1-eaa2-4e8d-84c1-0af09331b548", + "blob:http://127.0.0.1:8084/8e69f3ef-daf9-4083-9482-d8fb33f683b7", + "blob:http://127.0.0.1:8084/63cadfe8-d2fc-48cd-84fc-8468c9deecb4", + "blob:http://127.0.0.1:8084/0dd7b0cf-7366-4d3e-8ac1-21973c4d0561", + "blob:http://127.0.0.1:8084/f13d2f21-4180-4394-a4f3-cdf0568e06ee", + "blob:http://127.0.0.1:8084/b5825d33-a361-4477-9171-9a1855fe5ef4", + "blob:http://127.0.0.1:8084/7f92f756-518c-4dcb-8dbb-6c2c8c6b3265", + "blob:http://127.0.0.1:8084/59e5ae8b-94f7-4f17-b4f5-768db1750651", + "blob:http://127.0.0.1:8084/e74f0380-bf02-4a77-87ef-9c57eed3f33d", + "blob:http://127.0.0.1:8084/4fa687e5-c1c5-4c37-9d33-179ab330751f", + "blob:http://127.0.0.1:8084/94d11375-7683-4fc1-a6ec-15ad816e9262", + "blob:http://127.0.0.1:8084/4ded7a93-466c-4cca-8bff-6dec59f11a1a", + "blob:http://127.0.0.1:8084/2466518e-3456-4a2b-b196-130b8273f24c", + "blob:http://127.0.0.1:8084/5a030370-0c3d-4da5-8cb8-d3e19c3e3379", + "blob:http://127.0.0.1:8084/d5222f86-8bda-4a6f-ba92-231130195312" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/e9607d3b-cd9e-43d3-b79f-1cbf8980a94b", + "blob:http://127.0.0.1:8084/b323c86b-4b45-43a9-a167-6c5143719e60", + "blob:http://127.0.0.1:8084/447d1bed-ab23-4374-9f20-73e225e2a85b", + "blob:http://127.0.0.1:8084/562e128a-e521-43ed-90f6-72732c55dee5", + "blob:http://127.0.0.1:8084/6b22b7c0-adff-4c3e-9cf9-10cee649e3c0", + "blob:http://127.0.0.1:8084/8832a0c1-eaa2-4e8d-84c1-0af09331b548", + "blob:http://127.0.0.1:8084/8e69f3ef-daf9-4083-9482-d8fb33f683b7", + "blob:http://127.0.0.1:8084/63cadfe8-d2fc-48cd-84fc-8468c9deecb4", + "blob:http://127.0.0.1:8084/0dd7b0cf-7366-4d3e-8ac1-21973c4d0561", + "blob:http://127.0.0.1:8084/f13d2f21-4180-4394-a4f3-cdf0568e06ee", + "blob:http://127.0.0.1:8084/b5825d33-a361-4477-9171-9a1855fe5ef4", + "blob:http://127.0.0.1:8084/7f92f756-518c-4dcb-8dbb-6c2c8c6b3265", + "blob:http://127.0.0.1:8084/59e5ae8b-94f7-4f17-b4f5-768db1750651", + "blob:http://127.0.0.1:8084/e74f0380-bf02-4a77-87ef-9c57eed3f33d", + "blob:http://127.0.0.1:8084/4fa687e5-c1c5-4c37-9d33-179ab330751f", + "blob:http://127.0.0.1:8084/94d11375-7683-4fc1-a6ec-15ad816e9262", + "blob:http://127.0.0.1:8084/4ded7a93-466c-4cca-8bff-6dec59f11a1a", + "blob:http://127.0.0.1:8084/2466518e-3456-4a2b-b196-130b8273f24c", + "blob:http://127.0.0.1:8084/5a030370-0c3d-4da5-8cb8-d3e19c3e3379", + "blob:http://127.0.0.1:8084/31ab8dd6-96eb-4b74-aea7-cb15f945ec03", + "blob:http://127.0.0.1:8084/d5222f86-8bda-4a6f-ba92-231130195312" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 203, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 224, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/bcf47182-1e43-4c3d-a558-729e7a35be6f" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/bcf47182-1e43-4c3d-a558-729e7a35be6f", + "blob:http://127.0.0.1:8084/81e9c09f-b248-4de8-8491-f73b7295385f" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/81e9c09f-b248-4de8-8491-f73b7295385f" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 347, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/6da380f6-8cd4-4be4-b4b7-b3c61d594ca0", + "blob:http://127.0.0.1:8084/1597737e-6278-4644-90ef-8e676f664b73" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/6da380f6-8cd4-4be4-b4b7-b3c61d594ca0" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1785, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38895, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/40faddf3-2765-4505-9134-91d178aebb92", + "second": "blob:http://127.0.0.1:8084/88589279-74aa-45cb-8f85-aeccfec7db85", + "created": [ + "blob:http://127.0.0.1:8084/a457d7ac-e27a-4e38-9a59-3f5e3b74e65f", + "blob:http://127.0.0.1:8084/7e650732-c723-43ba-9c4b-c0422ba264a2", + "blob:http://127.0.0.1:8084/461da66c-ee9f-45b2-aa29-99d09b5948f0", + "blob:http://127.0.0.1:8084/5e3f9ad9-9ff2-4c1c-abd7-faf62186dfd6", + "blob:http://127.0.0.1:8084/435240a5-4548-47e0-b621-bca78c2ee144", + "blob:http://127.0.0.1:8084/97640aaa-e6c3-4494-a3b4-14f6f8730fdc", + "blob:http://127.0.0.1:8084/b29a6823-effa-4229-805d-5d774b45e55d", + "blob:http://127.0.0.1:8084/9902f5d9-96da-4210-91fe-f1b49ab78f36", + "blob:http://127.0.0.1:8084/1111a88d-100b-4efb-a10f-b00e88565f69", + "blob:http://127.0.0.1:8084/9de636ec-b1b3-470e-b7ff-6e6a853b3218", + "blob:http://127.0.0.1:8084/40faddf3-2765-4505-9134-91d178aebb92", + "blob:http://127.0.0.1:8084/ae6ff13c-e7e9-4e2c-bc19-c28922c00f42", + "blob:http://127.0.0.1:8084/2e2a3764-eea1-4789-972f-06f41e1a5e0a", + "blob:http://127.0.0.1:8084/6e0b8da7-1696-4951-97c7-02222fb91874", + "blob:http://127.0.0.1:8084/997b7a01-9ad2-4f8e-a280-6f05ea74acb5", + "blob:http://127.0.0.1:8084/d39d6483-d393-4ea2-b975-f91b7e33882d", + "blob:http://127.0.0.1:8084/b974c922-3dcf-460c-b565-f1ad06dc9618", + "blob:http://127.0.0.1:8084/843da1bd-9953-4c3f-b2e7-d8dbff60efd4", + "blob:http://127.0.0.1:8084/1500699a-2325-48b4-a7c6-3f9b23418dbf", + "blob:http://127.0.0.1:8084/0cd0abef-478c-41bd-9ffd-d89758c0fb5f", + "blob:http://127.0.0.1:8084/88589279-74aa-45cb-8f85-aeccfec7db85" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/7e650732-c723-43ba-9c4b-c0422ba264a2", + "blob:http://127.0.0.1:8084/461da66c-ee9f-45b2-aa29-99d09b5948f0", + "blob:http://127.0.0.1:8084/5e3f9ad9-9ff2-4c1c-abd7-faf62186dfd6", + "blob:http://127.0.0.1:8084/435240a5-4548-47e0-b621-bca78c2ee144", + "blob:http://127.0.0.1:8084/97640aaa-e6c3-4494-a3b4-14f6f8730fdc", + "blob:http://127.0.0.1:8084/b29a6823-effa-4229-805d-5d774b45e55d", + "blob:http://127.0.0.1:8084/9902f5d9-96da-4210-91fe-f1b49ab78f36", + "blob:http://127.0.0.1:8084/1111a88d-100b-4efb-a10f-b00e88565f69", + "blob:http://127.0.0.1:8084/9de636ec-b1b3-470e-b7ff-6e6a853b3218", + "blob:http://127.0.0.1:8084/40faddf3-2765-4505-9134-91d178aebb92", + "blob:http://127.0.0.1:8084/ae6ff13c-e7e9-4e2c-bc19-c28922c00f42", + "blob:http://127.0.0.1:8084/2e2a3764-eea1-4789-972f-06f41e1a5e0a", + "blob:http://127.0.0.1:8084/6e0b8da7-1696-4951-97c7-02222fb91874", + "blob:http://127.0.0.1:8084/997b7a01-9ad2-4f8e-a280-6f05ea74acb5", + "blob:http://127.0.0.1:8084/d39d6483-d393-4ea2-b975-f91b7e33882d", + "blob:http://127.0.0.1:8084/b974c922-3dcf-460c-b565-f1ad06dc9618", + "blob:http://127.0.0.1:8084/843da1bd-9953-4c3f-b2e7-d8dbff60efd4", + "blob:http://127.0.0.1:8084/1500699a-2325-48b4-a7c6-3f9b23418dbf", + "blob:http://127.0.0.1:8084/0cd0abef-478c-41bd-9ffd-d89758c0fb5f", + "blob:http://127.0.0.1:8084/a457d7ac-e27a-4e38-9a59-3f5e3b74e65f", + "blob:http://127.0.0.1:8084/88589279-74aa-45cb-8f85-aeccfec7db85" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 427, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 579, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/a8d7558d-779e-4bcb-9292-108321bc24fd" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/a8d7558d-779e-4bcb-9292-108321bc24fd", + "blob:http://127.0.0.1:8084/b2d66dd1-e3c9-4ac2-8834-8ea0aacb15b8" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/b2d66dd1-e3c9-4ac2-8834-8ea0aacb15b8" + ], + "repeated": "NotFoundError" + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 595, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/1cebe3e1-915c-43c0-9bed-d3ff9abb07f0", + "blob:http://127.0.0.1:8084/a1659107-5899-423b-8464-d467fa6af0ed" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/1cebe3e1-915c-43c0-9bed-d3ff9abb07f0" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1251, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / DOM drop dispatch exposes missing listener while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1321, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1354, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool workspace.legacy.js / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1372, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "workspace.legacy.js", + "sha256": "f77419cc62eeaa45c0413f4b04d169f78178fd539443cbf7b1e5db4ad4c95c98", + "recoveredIndividualFile": false, + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 544, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 44055, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/92bdcd14-288f-46f1-8ca1-086b9aa0d7cd", + "second": "blob:http://127.0.0.1:8084/bc838337-8afc-4e67-9ff1-a0cf377b2ecc", + "created": [ + "blob:http://127.0.0.1:8084/cce16f90-fff2-4fab-98e3-0dd4fe5530e0", + "blob:http://127.0.0.1:8084/986d6083-5a26-4e7d-a7f5-6a42654d9182", + "blob:http://127.0.0.1:8084/185e4ccc-2e8f-4225-a2a0-8bcae0406c9c", + "blob:http://127.0.0.1:8084/b0973256-7306-4675-b509-c0b0d97ebf8f", + "blob:http://127.0.0.1:8084/29c6f479-e206-48c4-a4c3-202146a3d9d8", + "blob:http://127.0.0.1:8084/7d029551-96e1-4fa1-9144-1b68807977cc", + "blob:http://127.0.0.1:8084/5636feb8-7701-4292-8cb3-28f965045e44", + "blob:http://127.0.0.1:8084/023fb75f-0ee2-4bcb-9768-cf87aac013ad", + "blob:http://127.0.0.1:8084/a637f267-0006-4d18-8d1a-b16c540ce871", + "blob:http://127.0.0.1:8084/1905ad99-702e-4acc-893b-3d8c37667676", + "blob:http://127.0.0.1:8084/92bdcd14-288f-46f1-8ca1-086b9aa0d7cd", + "blob:http://127.0.0.1:8084/8ac774e1-4e18-49b7-9ee9-73062f2676c0", + "blob:http://127.0.0.1:8084/7b7b3a61-2201-4f9c-8453-67c078139ade", + "blob:http://127.0.0.1:8084/844651f9-ec1c-460b-98a2-22b11d8f9a8e", + "blob:http://127.0.0.1:8084/ed57326d-07cf-4461-9088-ffdf5c65ea37", + "blob:http://127.0.0.1:8084/b600495a-beed-4ad8-b1b6-001209c78673", + "blob:http://127.0.0.1:8084/0ad835f8-84d2-46ba-8808-9637f8b10cb9", + "blob:http://127.0.0.1:8084/5a00fcb8-3b7f-4601-8b00-528c33ffe20b", + "blob:http://127.0.0.1:8084/5d1c74c3-f93e-4d60-b2eb-d768a063413c", + "blob:http://127.0.0.1:8084/4aecb783-0601-47f4-8c68-19c73a7e95ca", + "blob:http://127.0.0.1:8084/bc838337-8afc-4e67-9ff1-a0cf377b2ecc" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/986d6083-5a26-4e7d-a7f5-6a42654d9182", + "blob:http://127.0.0.1:8084/185e4ccc-2e8f-4225-a2a0-8bcae0406c9c", + "blob:http://127.0.0.1:8084/b0973256-7306-4675-b509-c0b0d97ebf8f", + "blob:http://127.0.0.1:8084/29c6f479-e206-48c4-a4c3-202146a3d9d8", + "blob:http://127.0.0.1:8084/7d029551-96e1-4fa1-9144-1b68807977cc", + "blob:http://127.0.0.1:8084/5636feb8-7701-4292-8cb3-28f965045e44", + "blob:http://127.0.0.1:8084/023fb75f-0ee2-4bcb-9768-cf87aac013ad", + "blob:http://127.0.0.1:8084/a637f267-0006-4d18-8d1a-b16c540ce871", + "blob:http://127.0.0.1:8084/1905ad99-702e-4acc-893b-3d8c37667676", + "blob:http://127.0.0.1:8084/92bdcd14-288f-46f1-8ca1-086b9aa0d7cd", + "blob:http://127.0.0.1:8084/8ac774e1-4e18-49b7-9ee9-73062f2676c0", + "blob:http://127.0.0.1:8084/7b7b3a61-2201-4f9c-8453-67c078139ade", + "blob:http://127.0.0.1:8084/844651f9-ec1c-460b-98a2-22b11d8f9a8e", + "blob:http://127.0.0.1:8084/ed57326d-07cf-4461-9088-ffdf5c65ea37", + "blob:http://127.0.0.1:8084/b600495a-beed-4ad8-b1b6-001209c78673", + "blob:http://127.0.0.1:8084/0ad835f8-84d2-46ba-8808-9637f8b10cb9", + "blob:http://127.0.0.1:8084/5a00fcb8-3b7f-4601-8b00-528c33ffe20b", + "blob:http://127.0.0.1:8084/5d1c74c3-f93e-4d60-b2eb-d768a063413c", + "blob:http://127.0.0.1:8084/4aecb783-0601-47f4-8c68-19c73a7e95ca", + "blob:http://127.0.0.1:8084/cce16f90-fff2-4fab-98e3-0dd4fe5530e0", + "blob:http://127.0.0.1:8084/bc838337-8afc-4e67-9ff1-a0cf377b2ecc" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 205, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 234, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/da99cb39-42be-423e-91d8-b992c48e39e2" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/da99cb39-42be-423e-91d8-b992c48e39e2", + "blob:http://127.0.0.1:8084/fc9e5e28-b8b9-4bd7-a37f-73eabb129110" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/fc9e5e28-b8b9-4bd7-a37f-73eabb129110" + ] + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "chromium", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 349, + "browser": "153.0.8010.12", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/4e905001-d2ef-4ec6-99ac-d0518c3021bc", + "blob:http://127.0.0.1:8084/2e1e655f-7799-4ae8-9458-b80b16039842" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/4e905001-d2ef-4ec6-99ac-d0518c3021bc" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 9120 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 1617, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-extraction", + "data": { + "width": 240, + "height": 210, + "sourceWidth": 320, + "sourceHeight": 180, + "cellHeight": 45, + "mime": "image/png", + "bytes": 38560, + "nonBlack": 3600, + "initialEvents": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + } + ], + "events": [ + { + "event": "file", + "progress": null, + "processing": false + }, + { + "event": "video", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "canvas", + "progress": null, + "processing": false + }, + { + "event": "update", + "progress": 0.1, + "processing": true + }, + { + "event": "update", + "progress": 0.2, + "processing": true + }, + { + "event": "update", + "progress": 0.3, + "processing": true + }, + { + "event": "update", + "progress": 0.4, + "processing": true + }, + { + "event": "update", + "progress": 0.5, + "processing": true + }, + { + "event": "update", + "progress": 0.6, + "processing": true + }, + { + "event": "update", + "progress": 0.7, + "processing": true + }, + { + "event": "update", + "progress": 0.8, + "processing": true + }, + { + "event": "update", + "progress": 0.9, + "processing": true + }, + { + "event": "update", + "progress": 1, + "processing": true + }, + { + "event": "done", + "progress": null, + "processing": false + }, + { + "event": "destroy", + "progress": null, + "processing": false + } + ], + "first": "blob:http://127.0.0.1:8084/5c1c8fed-0ed6-4519-9191-c2f2adfdece6", + "second": "blob:http://127.0.0.1:8084/fb9ac4a7-19d9-4d63-9d9a-0a14d8d7265b", + "created": [ + "blob:http://127.0.0.1:8084/5aa60b44-7be0-4a47-b057-cbdc0f69da18", + "blob:http://127.0.0.1:8084/03bfded8-11ce-4287-8167-5d779264af65", + "blob:http://127.0.0.1:8084/9c3d19b9-2c23-45ae-aa8c-877fc7e56ec7", + "blob:http://127.0.0.1:8084/f543053e-e514-46da-aaad-51151f2a4a44", + "blob:http://127.0.0.1:8084/4f6e7427-a7ff-4528-a8a7-3be20c37ac3c", + "blob:http://127.0.0.1:8084/01d276eb-2d84-4e63-a444-b63676510470", + "blob:http://127.0.0.1:8084/d309ee79-8939-4c48-a2db-dbf93a99c359", + "blob:http://127.0.0.1:8084/d6d6c9a3-46b5-4755-a6e9-638176bf46a2", + "blob:http://127.0.0.1:8084/6405f1cf-9ce0-4fe3-8e82-4d270c5d1d94", + "blob:http://127.0.0.1:8084/461aaaac-1f60-4ba6-961f-a04af499bacf", + "blob:http://127.0.0.1:8084/5c1c8fed-0ed6-4519-9191-c2f2adfdece6", + "blob:http://127.0.0.1:8084/b2c7cc8e-3459-4714-89a4-a05ec76534cd", + "blob:http://127.0.0.1:8084/df6202ae-515b-4bcf-9350-0f4e429d1b36", + "blob:http://127.0.0.1:8084/7816c39b-74b0-488c-9eeb-326bf2b38930", + "blob:http://127.0.0.1:8084/51041523-3e85-453f-9c13-65491e7e3611", + "blob:http://127.0.0.1:8084/6700989b-a669-4d4d-bf6b-b7e66d805c2f", + "blob:http://127.0.0.1:8084/dd23fc76-d702-4ba5-a946-01380c8413c3", + "blob:http://127.0.0.1:8084/568b4753-0918-4341-8f1b-25fd001e450e", + "blob:http://127.0.0.1:8084/aca820fc-6446-4966-affb-ca9088f0073d", + "blob:http://127.0.0.1:8084/d9a47094-a072-4c99-8fce-e8ebf22b313f", + "blob:http://127.0.0.1:8084/fb9ac4a7-19d9-4d63-9d9a-0a14d8d7265b" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/03bfded8-11ce-4287-8167-5d779264af65", + "blob:http://127.0.0.1:8084/9c3d19b9-2c23-45ae-aa8c-877fc7e56ec7", + "blob:http://127.0.0.1:8084/f543053e-e514-46da-aaad-51151f2a4a44", + "blob:http://127.0.0.1:8084/4f6e7427-a7ff-4528-a8a7-3be20c37ac3c", + "blob:http://127.0.0.1:8084/01d276eb-2d84-4e63-a444-b63676510470", + "blob:http://127.0.0.1:8084/d309ee79-8939-4c48-a2db-dbf93a99c359", + "blob:http://127.0.0.1:8084/d6d6c9a3-46b5-4755-a6e9-638176bf46a2", + "blob:http://127.0.0.1:8084/6405f1cf-9ce0-4fe3-8e82-4d270c5d1d94", + "blob:http://127.0.0.1:8084/461aaaac-1f60-4ba6-961f-a04af499bacf", + "blob:http://127.0.0.1:8084/5c1c8fed-0ed6-4519-9191-c2f2adfdece6", + "blob:http://127.0.0.1:8084/b2c7cc8e-3459-4714-89a4-a05ec76534cd", + "blob:http://127.0.0.1:8084/df6202ae-515b-4bcf-9350-0f4e429d1b36", + "blob:http://127.0.0.1:8084/7816c39b-74b0-488c-9eeb-326bf2b38930", + "blob:http://127.0.0.1:8084/51041523-3e85-453f-9c13-65491e7e3611", + "blob:http://127.0.0.1:8084/6700989b-a669-4d4d-bf6b-b7e66d805c2f", + "blob:http://127.0.0.1:8084/dd23fc76-d702-4ba5-a946-01380c8413c3", + "blob:http://127.0.0.1:8084/568b4753-0918-4341-8f1b-25fd001e450e", + "blob:http://127.0.0.1:8084/aca820fc-6446-4966-affb-ca9088f0073d", + "blob:http://127.0.0.1:8084/d9a47094-a072-4c99-8fce-e8ebf22b313f", + "blob:http://127.0.0.1:8084/5aa60b44-7be0-4a47-b057-cbdc0f69da18", + "blob:http://127.0.0.1:8084/fb9ac4a7-19d9-4d63-9d9a-0a14d8d7265b" + ], + "connected": false + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 453, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 613, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-media-failure", + "data": { + "failed": { + "code": 4, + "toolErrors": 0, + "first": "blob:http://127.0.0.1:8084/2512fe1b-200e-44ed-8a90-fbd1f6942ee4" + }, + "result": { + "value": "", + "created": [ + "blob:http://127.0.0.1:8084/2512fe1b-200e-44ed-8a90-fbd1f6942ee4", + "blob:http://127.0.0.1:8084/081662d9-300d-464a-98bf-f0ed073ce494" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/081662d9-300d-464a-98bf-f0ed073ce494" + ] + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "firefox", + "kind": "actual-tool-scenario", + "status": "passed", + "retry": 0, + "durationMs": 590, + "browser": "155.0", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-late-native-blob", + "data": { + "count": 1, + "created": [ + "blob:http://127.0.0.1:8084/437b4976-3e8f-4852-9a98-421903731a5f", + "blob:http://127.0.0.1:8084/d9a04deb-96e0-4116-8433-467d2d785967" + ], + "revoked": [ + "blob:http://127.0.0.1:8084/437b4976-3e8f-4852-9a98-421903731a5f" + ], + "pendingState": "pending", + "events": [ + "file", + "video", + "canvas", + "destroy", + "update" + ], + "connected": false, + "bytes": 6496 + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native file selection, seek extraction, PNG pixels and repeat generation", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1339, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / DOM drop dispatch uses the registered handler while callable ondrop works", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1323, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / corrupt media, replacement URLs and repeated destroy reproduce baseline gaps", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1299, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + }, + { + "title": "thumbnail-tool.spec.js / Thumbnail tool candidate-artifact / native PNG callback delivered after destroy still emits update and creates a URL", + "project": "webkit", + "kind": "blob-unavailable-control", + "status": "passed", + "retry": 0, + "durationMs": 1304, + "browser": "26.6", + "errors": [], + "measurements": [ + { + "name": "thumbnail-runtime", + "data": { + "name": "candidate-artifact", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1", + "originalNpmArchive": false, + "media": "test\\browser\\media\\thumbnail-pattern.mp4" + } + }, + { + "name": "thumbnail-blob-unavailable", + "data": { + "native": { + "http": "loaded", + "error": 4, + "blob": "error" + }, + "tool": { + "errors": 0, + "processing": false, + "duration": null + } + } + } + ] + } + ] + } + ] + }, + "inputs": [ + { + "file": "packages/artplayer-tool-thumbnail/src/index.js", + "sha256": "7da26db532a9c574ece83c7e714e27e7516f559ef3f95feb514cc80f5e105d7b" + }, + { + "file": "packages/artplayer-tool-thumbnail/src/input.js", + "sha256": "c003bcd012c84c97d5ebc6f59016e3657616126219f9e908a377ffbe372765b4" + }, + { + "file": "packages/artplayer-tool-thumbnail/src/sheet.js", + "sha256": "c671e298734e67d8d3f08bfcb383452f07cb4ed5a606f2903490181df0c0107c" + }, + { + "file": "packages/artplayer-tool-thumbnail/src/emitter.js", + "sha256": "5aa71e4317037c06b94e259beed2e964bbbb7117edbe78d29cc941c4916fd2ff" + }, + { + "file": "packages/artplayer-tool-thumbnail/src/utils.js", + "sha256": "dc19fe2f338df7058084eb2301d37db59ec4c914a85ba819a856d270c1267105" + }, + { + "file": "packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.js", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7" + }, + { + "file": "docs/compiled/artplayer-tool-thumbnail.js", + "sha256": "b0762a11caa57d3bd6713b8f03df196bdf1d443bc52b53b58f09561b3ade9cd7" + }, + { + "file": "packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.legacy.js", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1" + }, + { + "file": "docs/compiled/artplayer-tool-thumbnail.legacy.js", + "sha256": "e64319fc386346076229ea88d0396b5a7c3717c1152e44c9238fe01149a2c5b1" + }, + { + "file": "packages/artplayer-tool-thumbnail/dist/artplayer-tool-thumbnail.mjs", + "sha256": "292b1ccf58238b25914ce51aef474911794ec85a799fff222983fbbdb9948d21" + }, + { + "file": "docs/compiled/artplayer-tool-thumbnail.mjs", + "sha256": "292b1ccf58238b25914ce51aef474911794ec85a799fff222983fbbdb9948d21" + }, + { + "file": "packages/artplayer-tool-thumbnail/ARCHITECTURE.md", + "sha256": "34a0158913d107b52856e637f5d5e39153e8e8ca7543e2000f748bbf73b0bf0a" + }, + { + "file": "test/thumbnail-input.test.js", + "sha256": "08da28330bcd4ef83bddcea3aa10a95ad9ef075bdf3bb7daee734c0807f4b51a" + }, + { + "file": "test/helpers/thumbnail.js", + "sha256": "e547f3fe4581df6298ed448f1f672fe6e1fb501c3fbe60cc9be805a027fdab56" + }, + { + "file": "test/browser/thumbnail-input.spec.js", + "sha256": "df82785958860b550552507dde59a334d13d916985c0ac85673e210eeaaf3a38" + }, + { + "file": "test/browser/thumbnail-tool.spec.js", + "sha256": "cb457a3504ae49c129d65b3ddf066d6ead9781ef676a41e609a823536ae54a85" + }, + { + "file": "test/browser/thumbnail-native.spec.js", + "sha256": "50d2724c4903c2281cf7a5fa8577e4a8174742ac30b48cd3c679eaecc2d27f3e" + } + ], + "logs": [ + { + "file": "refactor/.cache/thumbnail03-input-before.log", + "sha256": "7b14971629f4b308ddf5c0981d3268fde88606db72afbb7d46964f953564a347" + }, + { + "file": "refactor/.cache/thumbnail03-input-source.log", + "sha256": "3db7549e487ef522a3be75a8b0706439d658816e3a589e5df7386c987408da49" + }, + { + "file": "refactor/.cache/thumbnail03-input-main.log", + "sha256": "54da4f1f2c77e9823295179242c7e0fde4d23d240d67ca8d9c4ff1e901892aad" + }, + { + "file": "refactor/.cache/thumbnail03-input-legacy.log", + "sha256": "6a86b8d34355323b6bfbc5bb24555a7fa0cc000269951dbda096bfb56c49f6d7" + }, + { + "file": "refactor/.cache/thumbnail03-input-build.log", + "sha256": "f70e661b7413b0101fa9b5e3f260736cd3c449b1709de8356d91f25a79642fb9" + }, + { + "file": "refactor/.cache/thumbnail03-input-lint.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "file": "refactor/.cache/thumbnail03-input-ci.log", + "sha256": "72b50eeee7428f665d09948ee4ed3882c1aaf6532ee3236a216da50f8be077d1" + }, + { + "file": "refactor/.cache/thumbnail03-input-imports.log", + "sha256": "e22f9823c6835acf1f77b1b1ea37bc498f55cba177581f25069b44337495b744" + }, + { + "file": "refactor/.cache/thumbnail03-input-browser-source.log", + "sha256": "9d0e43b9f544ea9113819a0a9f729309bbd543018aa5ff55929d5dd175e0debd" + }, + { + "file": "refactor/.cache/thumbnail03-input-browser-source.json", + "sha256": "45d1c0cc995ec97734688693874a765e16314a19445742842c23a19a9624dd1a" + }, + { + "file": "refactor/.cache/thumbnail03-input-browser-main.log", + "sha256": "98c024be98f4445efb79a75851788fe241b10bdd992ad6865405622a51260677" + }, + { + "file": "refactor/.cache/thumbnail03-input-browser-main.json", + "sha256": "3e8a09dd198308f2dffffc702b2c26f160e25f70aac8675931e1f1197b0b087e" + }, + { + "file": "refactor/.cache/thumbnail03-input-browser-legacy.log", + "sha256": "78d77898fa2416d1d25cdd2f704051a4e0d77518e2e03b1afac3fee11b3a2294" + }, + { + "file": "refactor/.cache/thumbnail03-input-browser-legacy.json", + "sha256": "bc9590c189fa8570a89a36225dcd22c3fca387bef5f529fa7b2a3653c41da61c" + } + ], + "limitations": [ + "03 remains doing; metadata/extraction/source cancellation and failure reentrancy still need implementation.", + "Each browser run has 16 Blob-unavailable controls, not successful Windows WebKit extraction.", + "Current coverage policy measures only core/chapter; no thumbnail percentage claimed.", + "Missing .esm.js/types and old default conflict remain open; no npm release, version bump or hosted CI run." + ] +} diff --git a/refactor/changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md b/refactor/changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md new file mode 100644 index 000000000..5800bd58b --- /dev/null +++ b/refactor/changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md @@ -0,0 +1,71 @@ +# PKG-TOOL-THUMB-03 input and sheet checkpoint + +Started from 1cb7779192cf552c0dfabcbb6de4f26b39e33045. Task 03 remains **doing**: +this checkpoint changes production input ownership and separates sheet/export +logic; extraction jobs and source/Blob cancellation still need implementation. + +## Source changes and compatibility + +`src/input.js` owns generated inputs, wrapper positioning and registered callbacks +in a private WeakMap. Setup validates before mutating committed options/DOM, +reuses an existing owned wrapper input, installs replacement listeners and then +cleans up the previous target. Caller-provided file inputs are retained. Failed +registration removes partial new listeners; failed construction rolls back owned +input/video resources. The historical instance ondrop method is now actually +registered for drop events. This repairs the undefined static callback defect. + +Destroy is idempotent and attempts all input/video/current-URL/event cleanup even +when a cleanup step throws. It preserves the first cleanup failure. Mutating the +public option field does not erase the input ownership record. After destruction, +setup/inputChange/ondrop/loadVideo cannot allocate new input/source resources. +Wrapper position is restored only when it still matches the tool's relative write. + +`src/sheet.js` contains midpoint coordinates, footer/canvas creation and download +anchor handling. Historical calculations, attribution, creat* spellings and +filename behavior stay unchanged. Download removes its temporary anchor even if +click fails. The public class delegates existing methods rather than adding new +public entry points. Constructor fields/order, direct class exports, defaults, +event timing and chaining remain covered. Runtime source is still JS pending 04; +emitter provenance and public declarations are not claimed complete. + +The package now has an actual ARCHITECTURE.md map, maintenance commands, ownership +rules and explicit continuation boundaries. Normal package builds regenerate +main/legacy/ESM plus docs copies. No hand editing of generated artifacts occurs. + +## Evidence + +`test/thumbnail-input.test.js` adds 14 candidate regressions. The unchanged tests +on frozen workspace main produce **2 passes/12 failures**. Source and both built +UMD variants pass all 14. These include real defect contrasts and compatibility +checks, not only assertions that new helper functions exist. + +Browser candidate coverage is added alongside frozen implementations. A separate +native DOM test selects files through generated inputs, replaces/reuses wrappers, +dispatches events to old detached inputs, verifies listener removal, restores +styles and verifies cleanup when a destroy listener throws. It runs without +requiring Blob media decoding and therefore also executes on Windows WebKit. + +Each source/main/legacy run contains 54 rows: 32 actual tool scenarios in +Chromium/Firefox across old and candidate versions, 3 candidate input/DOM scenarios +across all engines, 16 Windows WebKit Blob-unavailable controls and 3 native media +comparison tests. The 16 controls are not successful extraction. Old defect rows +remain unchanged; candidate drop and repeated-destroy expectations reflect fixes. +The candidate late-Blob and replacement-URL scenarios still reproduce outstanding +03 defects, explicitly preventing a claim of complete lifecycle repair. + +Final logs, per-case measurements, artifact hashes and CI results are recorded in +`refactor/baselines/thumbnail-input-checkpoint.json`. The current coverage policy +only measures core/chapter; no thumbnail coverage percentage is claimed here. +No hosted CI, physical Safari acceptance, npm publish or version bump occurred. + +## Remaining work and rollback + +Finish 03 with owned metadata waiting, extraction jobs, native error handling, +source/thumbnail URL lifetime and cancellation/late-callback protection. The +current pending extraction behavior is intentionally not declared fixed. Test +failure-path reentrancy during constructor/setup cleanup as part of that ownership +pass. Preserve the frozen default delay/height conflict until a concrete policy +is documented. Task 04 owns strict TS, emitter attribution and missing types; +05/06 retain full media/core integration, Safari/WebKit and distribution gates. +All thumbnail risks remain open. Revert this checkpoint and run the normal package +build to roll back the input/sheet change. The task completion count does not change. diff --git a/refactor/plan.md b/refactor/plan.md index 4d7b6b6d8..10c360fc6 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 222 项,范围 22 个包及工作区/示例。 -状态:todo 101 / doing 10 / blocked 0 / done 111 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 100 / doing 11 / blocked 0 / done 111 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -357,7 +357,7 @@ | --- | --- | --- | --- | --- | --- | --- | | PKG-TOOL-THUMB-01 | artplayer-tool-thumbnail
核对包契约与历史用法 | BASE-05 | 构造/defaults/事件/方法/历史拼写、.esm.js 入口和缺失 types | 源码/声明/README/demo/可恢复发布内容差异已登记;公开形状和版本范围冻结;区分旧 npm 的 main/CSS 与当前工作区无 main、.esm.js/类型缺失,不把工作区状态冒称旧 npm 发布事实 | H | done | | PKG-TOOL-THUMB-02 | artplayer-tool-thumbnail
建立特有行为与错误测试 | PKG-TOOL-THUMB-01, ENG-03, ENG-05 | 文件输入/拖放、抽帧网格、begin/end、进度/失败/重复任务 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | -| PKG-TOOL-THUMB-03 | artplayer-tool-thumbnail
整理内部职责与资源 | PKG-TOOL-THUMB-02, CORE-01 | 输入、抽帧队列、网格导出、URL/监听清理分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | todo | +| PKG-TOOL-THUMB-03 | artplayer-tool-thumbnail
整理内部职责与资源 | PKG-TOOL-THUMB-02, CORE-01 | 输入、抽帧队列、网格导出、URL/监听清理分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | doing | | PKG-TOOL-THUMB-04 | artplayer-tool-thumbnail
迁移自有源码和公开类型 | PKG-TOOL-THUMB-03, ENG-04, ENG-06, CORE-07 | 补齐真实 API 声明,自有 emitter/utils TS 化 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容;为 BASE-DIST-01 提供兼容入口/声明及消费者验证 | H | todo | | PKG-TOOL-THUMB-05 | artplayer-tool-thumbnail
验证新旧核心和组合 | PKG-TOOL-THUMB-04, CORE-22 | 工具独立浏览器使用,生成缩略图在核心中显示 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | | PKG-TOOL-THUMB-06 | artplayer-tool-thumbnail
验证分发并同步文档 | PKG-TOOL-THUMB-05, ENG-07 | tool.thumbnail.js、历史 ESM 兼容文件、types 路径和 tarball | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo | @@ -537,4 +537,5 @@ - PKG-IFRAME-05: [记录](changes/2026-09-13-PKG-IFRAME-05-integration.md) [记录](baselines/iframe-integration-validation.json) [记录](changes/2026-09-13-PKG-IFRAME-05-history.md) [记录](baselines/iframe-history-validation.json) - PKG-TOOL-THUMB-01: [记录](baselines/thumbnail-release.json) [记录](baselines/thumbnail-contract.md) [记录](changes/2026-09-13-PKG-TOOL-THUMB-01-contract.md) [记录](baselines/thumbnail-contract-validation.json) - PKG-TOOL-THUMB-02: [记录](baselines/thumbnail-behavior-validation.json) [记录](changes/2026-09-13-PKG-TOOL-THUMB-02-behavior.md) +- PKG-TOOL-THUMB-03: [记录](changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md) [记录](baselines/thumbnail-input-checkpoint.json) - PKG-FACTORY-01: [记录](baselines/factory-assignment-gaps.json) [记录](baselines/factory-compatibility-proposals.json) [记录](factory-compatibility-decision.md) [记录](changes/2026-09-12-PKG-FACTORY-01-decision.md) diff --git a/refactor/progress.md b/refactor/progress.md index 4dcc7513d..01657b2d5 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,17 @@ # 进度与证据 +## PKG-TOOL-THUMB-03 输入与导出源码检查点(doing) + +生产入口拆出input/sheet模块,修复drop注册、输入切换与wrapper所有权、构造/安装失败 +回滚、重复destroy及下载锚点清理;新增包内ARCHITECTURE.md。公开字段/方法/defaults +和正常事件顺序保持。14项新回归在旧版2通过/12失败,源码/main/legacy各14通过。 +三份浏览器各54项通过:32真实工具场景、3候选原生输入场景、16WebKit Blob不可用 +对照、3原生媒体对照;不把不可用对照算作成功抽帧。正常构建同步dist/docs副本。 +完整CI1620、330生产TS与3导入测试通过。队列/URL取消、迟到Blob和失败重入仍需继续, +本项不标done;04负责最终TS与声明。见[变更](changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md) +和[验证](baselines/thumbnail-input-checkpoint.json)。222项:111 done、11 doing、100 todo。 + + ## PKG-TOOL-THUMB-02 完成:抽帧、失败与资源基线 新增36项历史抽帧/生命周期测试,与26项契约共同通过;普通CI已接入新测试。 diff --git a/refactor/risks.json b/refactor/risks.json index 3690f2a55..38d4b59fc 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -3879,7 +3879,7 @@ "PKG-TOOL-THUMB-03", "PKG-TOOL-THUMB-05" ], - "compatibleResolution": "36 frozen behavior tests reproduce timer/input/source/callback ownership gaps and historical error ordering. Actual Chromium/Firefox native Blob callbacks prove late update and URL leaks after destroy. Task 03 must add corrected candidate regressions and owned cleanup; 05 retains real integration acceptance.", + "compatibleResolution": "03 input checkpoint fixes registered drop, input/wrapper ownership, failed setup/construction cleanup, repeated destroy and temporary download anchors. Candidate input regressions contrast 12 old failures; source/main/legacy verify preserved shape. Pending extraction callbacks, source URL replacement, cancellation and failure reentrancy remain open for the rest of 03 and real integration in 05.", "closureCriteria": "Deterministic old failure/candidate success for replacement, error and destruction plus real media/browser resource validation.", "status": "open", "evidence": [ @@ -3889,7 +3889,12 @@ "refactor/baselines/thumbnail-behavior-validation.json", "refactor/changes/2026-09-13-PKG-TOOL-THUMB-02-behavior.md", "test/thumbnail.test.js", - "test/browser/thumbnail-tool.spec.js" + "test/browser/thumbnail-tool.spec.js", + "refactor/changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md", + "packages/artplayer-tool-thumbnail/ARCHITECTURE.md", + "test/thumbnail-input.test.js", + "test/browser/thumbnail-input.spec.js", + "refactor/baselines/thumbnail-input-checkpoint.json" ] }, { diff --git a/refactor/tasks.json b/refactor/tasks.json index 17ae968fb..b8d2d34cf 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -3785,11 +3785,14 @@ "PKG-TOOL-THUMB-02", "CORE-01" ], - "status": "todo", + "status": "doing", "risk": "H", "deliverable": "输入、抽帧队列、网格导出、URL/监听清理分离", "acceptance": "结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过", - "evidence": [] + "evidence": [ + "changes/2026-09-13-PKG-TOOL-THUMB-03-input-checkpoint.md", + "baselines/thumbnail-input-checkpoint.json" + ] }, { "id": "PKG-TOOL-THUMB-04", diff --git a/test/browser/thumbnail-input.spec.js b/test/browser/thumbnail-input.spec.js new file mode 100644 index 000000000..57dba23b7 --- /dev/null +++ b/test/browser/thumbnail-input.spec.js @@ -0,0 +1,56 @@ +import { fileURLToPath } from 'node:url' +import { hash } from '../../refactor/scripts/releases.mjs' +import { thumbnailCandidate } from '../helpers/thumbnail.js' +import { expect, test } from './fixtures.js' + +const implementation = await thumbnailCandidate() +const sample = fileURLToPath(new URL('./media/thumbnail-pattern.mp4', import.meta.url)) + +test('Thumbnail input ownership replaces real DOM listeners and generated inputs', async ({ page }, testInfo) => { + await page.goto('/test/player.html?core=published') + await page.setContent('
') + await page.addScriptTag({ content: implementation.code }) + await page.evaluate(() => { + window.inputEvents = [] + window.inputTool = new window.ArtplayerToolThumbnail({ fileInput: document.querySelector('#first') }) + window.firstInput = window.inputTool.option.fileInput + window.inputTool.on('file', file => window.inputEvents.push(file.name)) + window.inputTool.setup({ fileInput: document.querySelector('#first') }) + }) + await expect(page.locator('#first input')).toHaveCount(1) + await page.locator('#first input').setInputFiles(sample) + const switched = await page.evaluate(() => { + const tool = window.inputTool + const firstInput = window.firstInput + const value = firstInput.value + tool.setup({ fileInput: document.querySelector('#second') }) + firstInput.dispatchEvent(new Event('change')) + firstInput.dispatchEvent(new Event('drop')) + return { value, events: window.inputEvents.slice(), firstPosition: document.querySelector('#first').style.position, disconnected: !firstInput.isConnected } + }) + expect(switched).toEqual({ value: '', events: ['thumbnail-pattern.mp4'], firstPosition: 'sticky', disconnected: true }) + await expect(page.locator('#first input')).toHaveCount(0) + await page.locator('#second input').setInputFiles(sample) + const result = await page.evaluate(() => { + const tool = window.inputTool + const input = tool.option.fileInput + const error = new Error('expected destroyed callback') + let notifications = 0 + tool.on('destroy', () => { + notifications++ + throw error + }) + let sameError = false + try { + tool.destroy() + } + catch (thrown) { sameError = thrown === error } + tool.destroy() + input.dispatchEvent(new Event('change')) + input.dispatchEvent(new Event('drop')) + tool.setup({ fileInput: document.querySelector('#first') }) + return { events: window.inputEvents, sameError, notifications, inputConnected: input.isConnected, videoConnected: tool.video.isConnected, secondPosition: document.querySelector('#second').style.position, inputs: document.querySelectorAll('input').length } + }) + expect(result).toEqual({ events: ['thumbnail-pattern.mp4', 'thumbnail-pattern.mp4'], sameError: true, notifications: 1, inputConnected: false, videoConnected: false, secondPosition: 'absolute', inputs: 0 }) + await testInfo.attach('thumbnail-input-ownership', { contentType: 'application/json', body: JSON.stringify({ implementation: implementation.name, sha256: hash(implementation.code), scope: 'Native file input/DOM/listeners only; does not claim media decoding.', switched, result }) }) +}) diff --git a/test/browser/thumbnail-tool.spec.js b/test/browser/thumbnail-tool.spec.js index d522e7561..6e34b93ee 100644 --- a/test/browser/thumbnail-tool.spec.js +++ b/test/browser/thumbnail-tool.spec.js @@ -3,7 +3,7 @@ import path from 'node:path' import process from 'node:process' import { fileURLToPath } from 'node:url' import { hash } from '../../refactor/scripts/releases.mjs' -import { thumbnailHistorical } from '../helpers/thumbnail.js' +import { thumbnailCandidate, thumbnailHistorical } from '../helpers/thumbnail.js' import { expect, test } from './fixtures.js' const sample = fileURLToPath(new URL('./media/thumbnail-pattern.mp4', import.meta.url)) @@ -27,7 +27,8 @@ async function capabilityControl(page, testInfo) { return true } -for (const implementation of thumbnailHistorical()) { +const implementations = [...thumbnailHistorical(), { ...await thumbnailCandidate(), inputOwnership: true }] +for (const implementation of implementations) { test.describe(`Thumbnail tool ${implementation.name}`, () => { test.beforeEach(async ({ page }, testInfo) => { await page.goto('/test/player.html?core=published') @@ -127,7 +128,7 @@ for (const implementation of thumbnailHistorical()) { await testInfo.attach('thumbnail-extraction', { contentType: 'application/json', body: JSON.stringify(result) }) }) - test('DOM drop dispatch exposes missing listener while callable ondrop works', async ({ page }, testInfo) => { + test(`DOM drop dispatch ${implementation.inputOwnership ? 'uses the registered handler' : 'exposes missing listener'} while callable ondrop works`, async ({ page }, testInfo) => { if (await capabilityControl(page, testInfo)) return const result = await page.evaluate(async () => { @@ -142,7 +143,7 @@ for (const implementation of thumbnailHistorical()) { tool.ondrop(event) return { fromListener, afterDirect: observed.filter(item => item.event === 'file').length, prevented: event.defaultPrevented } }) - expect(result).toEqual({ fromListener: { files: 0, prevented: false }, afterDirect: 1, prevented: true }) + expect(result).toEqual({ fromListener: { files: implementation.inputOwnership ? 1 : 0, prevented: !!implementation.inputOwnership }, afterDirect: implementation.inputOwnership ? 2 : 1, prevented: true }) await expect.poll(() => page.evaluate(() => tool.video.readyState)).toBeGreaterThanOrEqual(2) await page.evaluate(() => tool.destroy()) }) @@ -169,7 +170,7 @@ for (const implementation of thumbnailHistorical()) { expect(result.created).toHaveLength(2) expect(result.revoked).toEqual([result.created[1]]) expect(result.revoked).not.toContain(failed.first) - expect(result.repeated).toBe('NotFoundError') + expect(result.repeated).toBe(implementation.inputOwnership ? undefined : 'NotFoundError') expect(result.value === '').toBe(!implementation.legacy) await testInfo.attach('thumbnail-media-failure', { contentType: 'application/json', body: JSON.stringify({ failed, result }) }) }) diff --git a/test/helpers/thumbnail.js b/test/helpers/thumbnail.js index 5cc3239a6..b7a92294d 100644 --- a/test/helpers/thumbnail.js +++ b/test/helpers/thumbnail.js @@ -1,5 +1,14 @@ +import fs from 'node:fs' +import process from 'node:process' import vm from 'node:vm' import { verifyThumbnailContract } from '../../refactor/scripts/thumbnail-contract.mjs' +import { compilePackage } from './load.js' + +export async function thumbnailCandidate() { + if (process.env.ARTPLAYER_THUMBNAIL_BASELINE === '1') + return thumbnailHistorical().find(item => item.name === 'workspace.js') + return { name: process.env.ARTPLAYER_THUMBNAIL_ARTIFACT ? 'candidate-artifact' : 'candidate-source', code: process.env.ARTPLAYER_THUMBNAIL_ARTIFACT ? fs.readFileSync(process.env.ARTPLAYER_THUMBNAIL_ARTIFACT, 'utf8') : await compilePackage('artplayer-tool-thumbnail', 'umd') } +} export function thumbnailHistorical() { const { source, historical } = verifyThumbnailContract() diff --git a/test/thumbnail-input.test.js b/test/thumbnail-input.test.js new file mode 100644 index 000000000..6e52768bc --- /dev/null +++ b/test/thumbnail-input.test.js @@ -0,0 +1,218 @@ +import assert from 'node:assert/strict' +// eslint-disable-next-line test/no-import-node-test -- Candidate fixes also run against the frozen baseline. +import test from 'node:test' +import { thumbnailCandidate, thumbnailEnvironment } from './helpers/thumbnail.js' + +const implementation = await thumbnailCandidate() +function setup(wrapper = false) { + const env = thumbnailEnvironment(implementation) + const target = new env.Element(wrapper ? 'div' : 'input') + const instance = new env.Factory({ fileInput: target, number: 10, width: 20, height: 30, column: 3 }) + return { ...env, target, instance } +} + +test('Thumbnail input ownership preserves class methods, constructor fields and defaults', () => { + const { instance, Factory, exported } = setup() + assert.equal(typeof exported, 'function') + assert.equal(exported.default, undefined) + assert.deepEqual(Object.keys(instance), ['processing', 'option', 'video', 'duration', 'inputChange', 'ondrop']) + assert.deepEqual(Object.getOwnPropertyNames(Factory.prototype), ['constructor', 'ondrop', 'setup', 'inputChange', 'loadVideo', 'start', 'creatScreenshotDate', 'creatCanvas', 'download', 'errorHandle', 'destroy']) + assert.deepEqual(Object.keys(Factory.DEFAULTS), ['number', 'width', 'height', 'column', 'begin', 'end']) + assert.equal(instance.setup({ custom: 7 }), instance) + assert.equal(instance.option.custom, 7) + instance.destroy() +}) + +test('Thumbnail actual registered drop callback loads the first file and prevents default', () => { + const { instance, target } = setup() + const file = { name: 'drop.mp4', type: 'video/mp4' } + let prevented = 0 + for (const callback of target.handlers.get('drop') || []) + callback({ preventDefault() { prevented++ }, dataTransfer: { files: [file] } }) + assert.equal(instance.file, file) + assert.equal(prevented, 1) + assert.equal(target.handlers.get('drop').has(instance.ondrop), true) + instance.destroy() +}) + +test('Thumbnail replacing input moves all listeners and reads the new file', () => { + const { instance, target, Element } = setup() + const next = new Element('input') + assert.equal(instance.setup({ fileInput: next }), instance) + for (const name of ['change', 'dragover', 'drop']) { + assert.equal(target.handlers.get(name)?.size || 0, 0) + assert.equal(next.handlers.get(name)?.size, 1) + } + next.files = [{ name: 'new.mp4', type: 'video/mp4' }] + next.value = 'new.mp4' + for (const callback of next.handlers.get('change')) + callback({ target: next }) + assert.equal(instance.file, next.files[0]) + assert.equal(next.value, '') + instance.destroy() + assert.equal(next.handlers.get('change').size, 0) +}) + +test('Thumbnail repeated wrapper setup reuses the owned input and restores replaced wrapper style', () => { + const env = thumbnailEnvironment(implementation) + const first = new env.Element('div') + first.style.position = 'sticky' + const instance = new env.Factory({ fileInput: first }) + const input = instance.option.fileInput + instance.setup({ fileInput: first }) + assert.equal(first.children.length, 1) + assert.equal(instance.option.fileInput, input) + const second = new env.Element('div') + second.style.position = 'absolute' + instance.setup({ fileInput: second }) + assert.equal(first.children.length, 0) + assert.equal(first.style.position, 'sticky') + assert.equal(input.handlers.get('change').size, 0) + instance.destroy() + assert.equal(second.children.length, 0) + assert.equal(second.style.position, 'absolute') +}) + +test('Thumbnail does not overwrite a wrapper style changed by its owner', () => { + const { instance, target } = setup(true) + target.style.position = 'fixed' + instance.destroy() + assert.equal(target.children.length, 0) + assert.equal(target.style.position, 'fixed') +}) + +test('Thumbnail setup validation is atomic and cannot append an orphan input', () => { + const { instance, Element } = setup() + const previous = instance.option + const wrapper = new Element('div') + assert.throws(() => instance.setup({ fileInput: wrapper, width: 'invalid' }), /width/) + assert.equal(instance.option, previous) + assert.equal(wrapper.children.length, 0) + assert.equal(wrapper.style.position, undefined) + instance.destroy() +}) + +test('Thumbnail failed replacement listener installation removes partial listeners and keeps old ownership', () => { + const { instance, target, Element } = setup() + const next = new Element('input') + const failure = new Error('listener failed') + const add = next.addEventListener + next.addEventListener = function (name, callback) { + add.call(this, name, callback) + if (name === 'dragover') + throw failure + } + assert.throws(() => instance.setup({ fileInput: next }), error => error === failure) + assert.equal(instance.option.fileInput, target) + assert.equal(target.handlers.get('change').size, 1) + for (const callbacks of next.handlers.values()) + assert.equal(callbacks.size, 0) + instance.destroy() +}) + +test('Thumbnail failed video attachment rolls back generated input and attached video', () => { + const env = thumbnailEnvironment(implementation) + const wrapper = new env.Element('div') + wrapper.style.position = 'fixed' + const failure = new Error('append failed') + const append = env.body.appendChild + env.body.appendChild = function (child) { + append.call(this, child) + throw failure + } + assert.throws(() => new env.Factory({ fileInput: wrapper }), error => error === failure) + assert.equal(env.body.children.length, 0) + assert.equal(wrapper.children.length, 0) + assert.equal(wrapper.style.position, 'fixed') +}) + +test('Thumbnail failed constructor listener attachment removes every partial resource', () => { + const env = thumbnailEnvironment(implementation) + const target = new env.Element('input') + const failure = new Error('drop registration failed') + const add = target.addEventListener + target.addEventListener = function (name, callback) { + add.call(this, name, callback) + if (name === 'drop') + throw failure + } + assert.throws(() => new env.Factory({ fileInput: target }), error => error === failure) + assert.equal(env.body.children.length, 0) + for (const callbacks of target.handlers.values()) + assert.equal(callbacks.size, 0) +}) + +test('Thumbnail externally detached video and repeated destroy are safe', () => { + const { instance, body, target } = setup() + let count = 0 + instance.on('destroy', () => count++) + body.removeChild(instance.video) + assert.equal(instance.destroy(), undefined) + assert.equal(instance.destroy(), undefined) + assert.equal(count, 1) + for (const callbacks of target.handlers.values()) + assert.equal(callbacks.size, 0) +}) + +test('Thumbnail destroy uses private input ownership despite public option replacement', () => { + const { instance, target, Element } = setup(true) + const ownedInput = instance.option.fileInput + instance.option = { fileInput: new Element('input') } + instance.destroy() + assert.equal(target.children.length, 0) + for (const callbacks of ownedInput.handlers.values()) + assert.equal(callbacks.size, 0) +}) + +test('Thumbnail cleanup continues after listener removal failure and cannot reload after destroy', () => { + const { instance, target, body, operations, Element } = setup() + instance.loadVideo({ name: 'first.mp4', type: 'video/mp4' }) + const failure = new Error('remove failed') + const remove = target.removeEventListener + target.removeEventListener = function (name, callback) { + if (name === 'change') + throw failure + remove.call(this, name, callback) + } + let count = 0 + instance.on('destroy', () => count++) + assert.throws(() => instance.destroy(), error => error === failure) + assert.equal(body.children.length, 0) + assert.equal(count, 1) + assert.equal(target.handlers.get('dragover').size, 0) + assert.equal(operations.filter(item => item.name === 'revokeURL').length, 1) + const wrapper = new Element('div') + assert.equal(instance.setup({ fileInput: wrapper }), instance) + instance.loadVideo({ name: 'late.mp4', type: 'video/mp4' }) + instance.inputChange({ target }) + instance.ondrop({ preventDefault() { + throw new Error('should not run') + } }) + assert.equal(wrapper.children.length, 0) + assert.equal(operations.filter(item => item.name === 'createURL').length, 1) + assert.equal(instance.destroy(), undefined) +}) + +test('Thumbnail download removes its temporary anchor even when click fails', () => { + const { instance, Element, body } = setup() + instance.file = { name: 'video.part.mp4' } + instance.thumbnailUrl = 'blob:sheet' + const failure = new Error('click failed') + Element.prototype.click = () => { + throw failure + } + assert.throws(() => instance.download(), error => error === failure) + assert.deepEqual(body.children.map(child => child.tagName), ['VIDEO']) + instance.destroy() +}) + +test('Thumbnail extracted sheet helpers preserve midpoint coordinates and footer', () => { + const { instance, operations } = setup() + instance.duration = 100 + assert.deepEqual(JSON.parse(JSON.stringify(instance.creatScreenshotDate())), Array.from({ length: 10 }, (_, i) => ({ time: 5 + i * 10, x: i % 3 * 20, y: Math.floor(i / 3) * 30 }))) + const canvas = instance.creatCanvas() + assert.equal(canvas.width, 60) + assert.equal(canvas.height, 150) + assert.deepEqual(operations.find(item => item.name === 'fillText').args, ['From: https://artplayer.org/, Number: 10, Width: 20, Height: 30, Column: 3', 10, 139]) + instance.destroy() +})