mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-10 21:06:15 -08:00
refactor(core): CORE-04 scope initialization and make destruction reentrant-safe
This commit is contained in:
1 parent
3e38dd0d19
commit
4eec8112fa
32 files changed
+2779
-189
No files matched your search
@@ -0,0 +1,92 @@
|
||||
import assert from 'node:assert/strict'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Use the repository Node test runner.
|
||||
import { test } from 'node:test'
|
||||
import { loadModules } from './helpers/load.js'
|
||||
|
||||
const file = 'packages/artplayer/src/lifecycle/instance'
|
||||
const { beginLifecycle, destroyInstance, finishLifecycle, getScope, urlMix } = await loadModules({
|
||||
...Object.fromEntries(['beginLifecycle', 'destroyInstance', 'finishLifecycle', 'getScope'].map(name => [name, { file, name }])),
|
||||
urlMix: 'packages/artplayer/src/player/urlMix',
|
||||
})
|
||||
|
||||
test('instance teardown preserves order, public state and first-call removeHtml across reentry', () => {
|
||||
const calls = []
|
||||
const instances = []
|
||||
const owner = {
|
||||
isDestroy: false,
|
||||
reset() {
|
||||
calls.push(['reset', this.isDestroy])
|
||||
destroyInstance(this, instances, true, true)
|
||||
},
|
||||
template: { $video: {}, destroy(removeHtml) {
|
||||
calls.push(['template', removeHtml])
|
||||
} },
|
||||
emit(name) {
|
||||
calls.push([name, this.isDestroy, instances.includes(this)])
|
||||
},
|
||||
}
|
||||
const keys = Object.keys(owner)
|
||||
beginLifecycle(owner)
|
||||
assert.deepEqual(Object.keys(owner), keys)
|
||||
getScope(owner).add(() => {
|
||||
calls.push(['resources', owner.isDestroy])
|
||||
})
|
||||
assert(finishLifecycle(owner))
|
||||
instances.push(owner)
|
||||
destroyInstance(owner, instances, false, true)
|
||||
destroyInstance(owner, instances, true, true)
|
||||
assert.deepEqual(calls, [['reset', false], ['resources', false], ['template', false], ['destroy', true, false]])
|
||||
})
|
||||
|
||||
test('reset failure still releases resources, removes the instance and dispatches destroy', () => {
|
||||
const error = new Error('reset failed')
|
||||
let released = false
|
||||
let emitted = false
|
||||
const owner = { isDestroy: false, reset() {
|
||||
throw error
|
||||
}, template: { $video: {}, destroy() {} }, emit() { emitted = true } }
|
||||
const instances = [owner]
|
||||
beginLifecycle(owner)
|
||||
getScope(owner).add(() => {
|
||||
released = true
|
||||
})
|
||||
assert.throws(() => destroyInstance(owner, instances, true, true), value => value === error)
|
||||
assert(released && emitted && owner.isDestroy)
|
||||
assert.deepEqual(instances, [])
|
||||
destroyInstance(owner, instances, true, true)
|
||||
})
|
||||
|
||||
test('destroy listener error propagates unchanged after internal cleanup and remains consumed', () => {
|
||||
const error = new Error('listener failed')
|
||||
const sibling = {}
|
||||
const owner = { isDestroy: false, reset() {}, emit() {
|
||||
throw error
|
||||
} }
|
||||
const instances = [owner, sibling]
|
||||
beginLifecycle(owner)
|
||||
assert.throws(() => destroyInstance(owner, instances, true, false), value => value === error)
|
||||
assert(getScope(owner).closed)
|
||||
destroyInstance(owner, instances, true, false)
|
||||
assert.deepEqual(instances, [sibling])
|
||||
})
|
||||
|
||||
test('custom-type continuation cannot start after its timer resolves but before its owner is destroyed', async (context) => {
|
||||
context.mock.timers.enable({ apis: ['setTimeout'] })
|
||||
let calls = 0
|
||||
const owner = {
|
||||
isDestroy: false,
|
||||
reset() {},
|
||||
emit() {},
|
||||
option: { type: 'custom', customType: { custom() { calls++ } } },
|
||||
template: { $video: { src: '' }, destroy() {} },
|
||||
loading: { show: false },
|
||||
}
|
||||
beginLifecycle(owner)
|
||||
urlMix(owner)
|
||||
owner.url = 'test.custom'
|
||||
context.mock.timers.tick(0)
|
||||
destroyInstance(owner, [], true, false)
|
||||
await Promise.resolve()
|
||||
assert.equal(calls, 0)
|
||||
assert.equal(owner.loading.show, false)
|
||||
})
|
||||
Reference in new issue
Block a user