mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-23 22:01:20 -08:00
fix(auto-thumbnail): [PKG-AUTO-THUMB-12] release stalled metadata loads
This commit is contained in:
1 parent
d3aa4bbfe4
commit
42ddead0cd
20 files changed
+6048
-20
No files matched your search
@@ -0,0 +1,102 @@
|
||||
import assert from 'node:assert/strict'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Verify metadata wait ownership and cancellation.
|
||||
import test from 'node:test'
|
||||
import { autoThumbnailCandidate, autoThumbnailEnvironment } from './helpers/auto-thumbnail.js'
|
||||
|
||||
const implementation = await autoThumbnailCandidate()
|
||||
async function setup() {
|
||||
const env = autoThumbnailEnvironment(implementation)
|
||||
const result = await env.factory({ width: 80, number: 1 })(env.art)
|
||||
assert.equal(result.name, 'artplayerPluginAutoThumbnail')
|
||||
env.art.emit('video:loadedmetadata')
|
||||
return env
|
||||
}
|
||||
|
||||
function released(env, video = env.videos[0]) {
|
||||
assert.equal(env.attached.has(video), false)
|
||||
assert.equal(video.src, undefined)
|
||||
assert.equal(video.onloadedmetadata, null)
|
||||
assert.equal(video.onerror, null)
|
||||
}
|
||||
|
||||
test('Auto-thumbnail metadata timeout releases a stalled decoder and ignores late metadata', async () => {
|
||||
const env = await setup()
|
||||
const metadata = env.videos[0].onloadedmetadata
|
||||
const deadline = [...env.timers.values()][0]
|
||||
assert(deadline, 'Metadata loading must have an owned deadline')
|
||||
assert.equal(deadline.delay, 30000)
|
||||
deadline.callback()
|
||||
released(env)
|
||||
assert.equal(env.timers.size, 0)
|
||||
assert.equal(env.warnings.length, 1)
|
||||
assert.match(env.warnings[0][1].message, /metadata timed out/)
|
||||
metadata()
|
||||
deadline.callback()
|
||||
assert.equal(env.canvases.length, 0)
|
||||
assert.equal(env.updates.length, 0)
|
||||
assert.equal(env.warnings.length, 1)
|
||||
env.art.emit('destroy')
|
||||
})
|
||||
|
||||
for (const scenario of ['destroy', 'restart', 'error', 'metadata']) {
|
||||
test(`Auto-thumbnail metadata deadline becomes inert after ${scenario}`, async () => {
|
||||
const env = await setup()
|
||||
const deadline = [...env.timers.values()][0]
|
||||
assert(deadline, 'Metadata loading must have an owned deadline')
|
||||
if (scenario === 'metadata') {
|
||||
env.metadata()
|
||||
const frameDeadline = [...env.timers.values()][0]
|
||||
assert.notEqual(frameDeadline, deadline)
|
||||
deadline.callback()
|
||||
assert.equal(env.timers.size, 1, 'A queued metadata timeout cannot cancel the new frame wait')
|
||||
env.seeked()
|
||||
env.finish()
|
||||
assert.equal(env.updates.length, 1)
|
||||
}
|
||||
else if (scenario === 'error') {
|
||||
env.videos[0].error = new Error('Media failed')
|
||||
env.videos[0].onerror()
|
||||
}
|
||||
else {
|
||||
env.art.emit(scenario)
|
||||
}
|
||||
deadline.callback()
|
||||
released(env)
|
||||
assert.equal(env.timers.size, 0)
|
||||
assert.equal(env.warnings.length, scenario === 'error' ? 1 : 0)
|
||||
env.art.emit('destroy')
|
||||
})
|
||||
}
|
||||
|
||||
test('Auto-thumbnail stalled replacement retains the previous usable sheet', async () => {
|
||||
const env = await setup()
|
||||
env.metadata()
|
||||
env.seeked()
|
||||
env.finish()
|
||||
const sheet = env.art.thumbnails
|
||||
env.art.emit('restart')
|
||||
env.art.emit('video:loadedmetadata')
|
||||
const deadline = [...env.timers.values()][0]
|
||||
assert(deadline, 'Replacement metadata loading must have a deadline')
|
||||
deadline.callback()
|
||||
released(env, env.videos[1])
|
||||
assert.equal(env.art.thumbnails, sheet)
|
||||
assert.equal(env.urls.has(sheet.url), true)
|
||||
assert.equal(env.updates.length, 1)
|
||||
env.art.emit('destroy')
|
||||
assert.equal(env.urls.size, 0)
|
||||
})
|
||||
|
||||
test('Auto-thumbnail metadata timer registration cannot start loading after destruction', async () => {
|
||||
const env = autoThumbnailEnvironment(implementation)
|
||||
await env.factory({ width: 80, number: 1 })(env.art)
|
||||
const schedule = env.box.setTimeout
|
||||
env.box.setTimeout = (...args) => {
|
||||
env.art.emit('destroy')
|
||||
return schedule(...args)
|
||||
}
|
||||
env.art.emit('video:loadedmetadata')
|
||||
released(env)
|
||||
assert.equal(env.timers.size, 0)
|
||||
assert.equal(env.canvases.length, 0)
|
||||
})
|
||||
Reference in new issue
Block a user