mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-13 07:46:17 -08:00
test(PKG-HLS-SDK-01): checkpoint direct HTTP teardown crashes
This commit is contained in:
1 parent
fe5534ac24
commit
3316b8a867
8 files changed
+1516
-10
No files matched your search
@@ -127,3 +127,10 @@ For unresolved Firefox grouped-stream diagnostics, use
|
||||
`--observe-workers` uses the same native-worker observer as the integration suite. Each run retains
|
||||
its own report and trace files. See the HLS-SDK-01 in-progress record: one target crash and a separate
|
||||
group-switch stall remain unclassified. Passing diagnostic repetitions are not release evidence.
|
||||
|
||||
The diagnostic runner records host-side failure/crash phases. Optional
|
||||
`--capture-before-destroy` saves media/SDK events outside the page before teardown;
|
||||
it adds an evaluate and may change timing, so it is off by default. Direct ordinary
|
||||
HTTP without ArtPlayer/plugin or a Worker observer still reproduced crashes with
|
||||
both reset-first and SDK-first teardown. A passing no-worker control does not
|
||||
replace worker acceptance. See the 2026-09-14 HTTP teardown checkpoint in refactor.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,70 @@
|
||||
# PKG-HLS-SDK-01: direct HTTP teardown diagnostic checkpoint
|
||||
|
||||
Status remains doing. Baseline fe5534ac2429ac67702ca9d4121b4ab8603cb278.
|
||||
No production source, dependency, fixture, build output or acceptance assertion
|
||||
was changed. This checkpoint advances attribution, not completion.
|
||||
|
||||
## Controls and results
|
||||
|
||||
All five runs use frozen Hls.js1.5.17, Windows Firefox155.0, local ordinary HTTP,
|
||||
direct native video, no ArtPlayer/plugin, no route interception, no Worker
|
||||
observer and no SDK logger. Native worker output is not substituted. Browser
|
||||
process DEBUG logging is enabled and saved for every run. Existing trace capture
|
||||
and media/SDK event recording remain enabled, so these are not uninstrumented runs.
|
||||
|
||||
| Run | Teardown | Worker | Extra pre-destroy snapshot | Pass | Fail |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Original runner | reset first | yes | no | 9 | 1 |
|
||||
| Original runner control | reset first | no | no | 10 | 0 |
|
||||
| Phase/snapshot runner | reset first | yes | yes | 5 | 0 |
|
||||
| Final phase runner | reset first | yes | no | 4 | 1 |
|
||||
| Final phase runner | SDK first | yes | no | 3 | 2 |
|
||||
|
||||
35 diagnostic iterations total:31 pass,4 fail. These are finite controls, not
|
||||
release-matrix passes or a claim about long-term failure probability. The no-worker
|
||||
control cannot substitute for required worker acceptance. Snapshot success may
|
||||
reflect changed timing; it is not evidence of a repair.
|
||||
|
||||
The three failures in the final phase runner occur during final-state collection,
|
||||
after destroy and the immediate post-destroy state call returned. The first failure
|
||||
predates phase recording and cannot be assigned the same precise stage. Original
|
||||
errors, trace hashes and logs are retained separately from previous diagnostics.
|
||||
Both reset-first and SDK-first reproduce failures. Do not change the public core
|
||||
destroy order or callers' SDK configuration based on the previously passing
|
||||
SDK-first samples. No grouped-playback timeout occurred in these direct controls;
|
||||
the independent HLS-PLAYBACK-01 failure remains unclosed.
|
||||
|
||||
## Browser evidence limits
|
||||
|
||||
The installed Firefox1543 archive's TargetRegistry.js observes
|
||||
`oop-frameloader-crashed`, emits the target crash event and disposes that target.
|
||||
The logged stack reaches this observer. The source member hash and excerpt are
|
||||
recorded with the actual binary archive hash, not inferred from another release.
|
||||
This supports a browser out-of-process frame-loader crash notification; it is not
|
||||
a native stack, minidump or proof of the responsible decoder/worker/SDK component.
|
||||
The browser parent exits normally after explicit teardown. Its exit code0 does
|
||||
not negate page crashes. The SWGL framebuffer startup warning occurs in both the
|
||||
failing worker run and passing no-worker control, so it is not a root-cause claim.
|
||||
|
||||
## Maintained diagnostic changes
|
||||
|
||||
The runner now records host-side operation phases and the phase/time of crash
|
||||
events. Errors during final state, tracing or context close remain failures even
|
||||
after operation assertions passed. This introduces no page calls in default mode.
|
||||
`--capture-before-destroy` optionally saves media, SDK and event state to Node
|
||||
before destroying the page; it defaults off and is explicitly listed in reports.
|
||||
That extra evaluate may affect timing, which is why its passing control is kept
|
||||
separate. Existing7-second waits, retries, media, SDK and worker settings are intact.
|
||||
|
||||
Script lint and the frozen SDK/worker archive check pass. Package source and all
|
||||
published build outputs remain unchanged, so no package rebuild is required.
|
||||
See [evidence](../baselines/hls-http-teardown-validation.json) for exact runner,
|
||||
SDK/media inputs, reports, traces and failure classification.
|
||||
|
||||
## Next evidence
|
||||
|
||||
HLS-CRASH-01 and HLS-PLAYBACK-01 remain open; task SDK-01 is not complete. Obtain
|
||||
native Firefox content-process crash diagnostics or a minimized MSE reproduction
|
||||
and independently investigate the grouped-stream stall. Continue other package
|
||||
tasks while keeping this gate visible. Reverting this checkpoint removes diagnostic
|
||||
phase/snapshot metadata only and restores no production behavior.
|
||||
+1
-1
@@ -548,7 +548,7 @@
|
||||
- PKG-HLS-02: [记录](hls-validation.md) [记录](baselines/hls-sdk.json) [记录](baselines/hls-validation.json) [记录](changes/2026-09-11-PKG-HLS-02-tests.md)
|
||||
- PKG-HLS-03: [记录](changes/2026-09-12-PKG-HLS-03-modules.md) [记录](baselines/hls-modules-validation.json) [记录](hls-validation.md)
|
||||
- PKG-HLS-04: [记录](changes/2026-09-12-PKG-HLS-04-types.md) [记录](baselines/hls-types-validation.json) [记录](hls-validation.md)
|
||||
- PKG-HLS-SDK-01: [记录](changes/2026-09-12-PKG-HLS-SDK-01-integration.md) [记录](baselines/hls-sdk-validation.json) [记录](baselines/hls-sdk-diagnostics.json)
|
||||
- PKG-HLS-SDK-01: [记录](changes/2026-09-12-PKG-HLS-SDK-01-integration.md) [记录](baselines/hls-sdk-validation.json) [记录](baselines/hls-sdk-diagnostics.json) [记录](changes/2026-09-14-PKG-HLS-SDK-01-http-teardown.md) [记录](baselines/hls-http-teardown-validation.json)
|
||||
- PKG-DASH-01: [记录](changes/2026-09-12-PKG-DASH-01-contract.md) [记录](baselines/dash-control-contract.md) [记录](baselines/dash-control-release.json)
|
||||
- PKG-DASH-02: [记录](changes/2026-09-12-PKG-DASH-02-tests.md) [记录](dash-validation.md) [记录](baselines/dash-validation.json)
|
||||
- PKG-DASH-03: [记录](changes/2026-09-12-PKG-DASH-03-runtime.md) [记录](baselines/dash-runtime.json) [记录](dash-validation.md)
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# 进度与证据
|
||||
|
||||
## PKG-HLS-SDK-01 普通HTTP销毁诊断检查点(仍未完成)
|
||||
|
||||
直接原生video、Hls1.5.17、Firefox155.0、普通HTTP且无ArtPlayer/插件/Worker观察器,
|
||||
35次诊断31通过4失败。关闭Worker的10次及可选销毁前快照5次通过不能替代正常验收;
|
||||
先销毁SDK也失败2/5,因此不能把销毁顺序当作修复。新增主机侧阶段记录,三次有阶段
|
||||
证据的崩溃发生在destroy已返回后的最终状态读取。当前Firefox调试源码接收到
|
||||
oop-frameloader-crashed,但没有原生堆栈来确定责任组件;SWGL警告两种控制均存在。
|
||||
见[检查点](changes/2026-09-14-PKG-HLS-SDK-01-http-teardown.md)及[证据](baselines/hls-http-teardown-validation.json)。只改诊断/文档,生产和产物未变。
|
||||
脚本lint和SDK归档验证通过,原崩溃/切组失败均保留,SDK-01仍doing;253项统计不变。
|
||||
下一步需要Firefox原生崩溃诊断或更小MSE复现,切组卡住独立排查。VAST初始化选择仍待
|
||||
用户回复,继续不依赖这些决定的包验收工作;不改核心销毁顺序或放宽worker门槛。
|
||||
|
||||
## PKG-VAST-07 旧default调用兼容完成
|
||||
|
||||
VAST入口增加default自身别名,恢复旧require(...).default调用并保留现有直接调用。
|
||||
|
||||
+5
-2
@@ -2688,10 +2688,13 @@
|
||||
"test/browser/hls-sdk.spec.js",
|
||||
"refactor/changes/2026-09-12-PKG-HLS-SDK-01-integration.md",
|
||||
"refactor/baselines/hls-sdk-diagnostics.json",
|
||||
"refactor/scripts/hls-sdk-diagnostic.mjs"
|
||||
"refactor/scripts/hls-sdk-diagnostic.mjs",
|
||||
"refactor/changes/2026-09-14-PKG-HLS-SDK-01-http-teardown.md",
|
||||
"refactor/baselines/hls-http-teardown-validation.json"
|
||||
],
|
||||
"compatibleResolution": "直接原生 video(无 ArtPlayer/插件)和候选核心已有 page crashed;候选核心无观察器也复现。继续区分 SDK、Firefox/Playwright 与媒体销毁,不静默改核心 destroy 顺序或调用方 SDK 配置。",
|
||||
"closureCriteria": "取得可解释的崩溃诊断或直接 SDK 对照;验证处置和新旧核心/worker/分组销毁矩阵,不能仅以再次通过关闭。"
|
||||
"closureCriteria": "取得可解释的崩溃诊断或直接 SDK 对照;验证处置和新旧核心/worker/分组销毁矩阵,不能仅以再次通过关闭。",
|
||||
"workspaceState": "2026-09-14 direct HTTP/no ArtPlayer/plugin/Worker observer:35 diagnostics,31 passed4 failed. Worker reset-first fails1/10 and1/5; no-worker10/10 and optional pre-destroy snapshot5/5 pass. SDK-first also fails2/5. Three phase-recorded crashes occur during final-state collection after destroy returned. Installed Firefox TargetRegistry observer receives oop-frameloader-crashed; no native stack/root cause established. Do not substitute no-worker/snapshot success or change core teardown order; risk remains open."
|
||||
},
|
||||
{
|
||||
"id": "HLS-PLAYBACK-01",
|
||||
|
||||
@@ -10,7 +10,7 @@ import { observeWorkers } from '../../test/helpers/worker-observer.js'
|
||||
import { ensureArchive, hash, readMember, refactorDir } from './releases.mjs'
|
||||
|
||||
// Direct SDK control: no ArtPlayer or plugin is loaded, and no worker output is substituted.
|
||||
export async function diagnose({ version = '1.7.2', iterations = 5, transport = 'http', teardown = 'reset-first', worker = true, host = 'direct', plugin = false, sdkLogs = false, workerObserver = false } = {}) {
|
||||
export async function diagnose({ version = '1.7.2', iterations = 5, transport = 'http', teardown = 'reset-first', worker = true, host = 'direct', plugin = false, sdkLogs = false, workerObserver = false, captureBeforeDestroy = false } = {}) {
|
||||
const runnerSHA256 = hash(fs.readFileSync(new URL(import.meta.url)))
|
||||
const observerSHA256 = hash(fs.readFileSync(new URL('../../test/helpers/worker-observer.js', import.meta.url)))
|
||||
assert(Number.isInteger(iterations) && iterations > 0 && iterations <= 50)
|
||||
@@ -66,10 +66,13 @@ export async function diagnose({ version = '1.7.2', iterations = 5, transport =
|
||||
await context.tracing.start({ screenshots: true, snapshots: true, sources: true })
|
||||
const page = await context.newPage()
|
||||
const wait = predicate => expect.poll(() => page.evaluate(predicate), { timeout: 7000 }).toBe(true)
|
||||
const entry = { iteration, status: 'running', errors: [], requests: [] }
|
||||
const entry = { iteration, status: 'running', errors: [], requests: [], phase: 'setup', crashes: [] }
|
||||
results.push(entry)
|
||||
page.on('pageerror', error => entry.errors.push(error.message))
|
||||
page.on('crash', () => entry.errors.push('page crashed'))
|
||||
page.on('crash', () => {
|
||||
entry.errors.push('page crashed')
|
||||
entry.crashes.push({ phase: entry.phase, at: new Date().toISOString() })
|
||||
})
|
||||
page.on('requestfailed', request => entry.requests.push({ url: request.url(), error: request.failure() }))
|
||||
if (transport === 'route') {
|
||||
await page.route('**/*.m3u8', route => serveRoute(route))
|
||||
@@ -163,9 +166,11 @@ export async function diagnose({ version = '1.7.2', iterations = 5, transport =
|
||||
},
|
||||
}
|
||||
}, { worker, teardown, host, plugin, sdkLogs })
|
||||
entry.phase = 'initial-playback'
|
||||
await wait(() => window.direct.video?.readyState >= 3)
|
||||
await page.evaluate(() => window.direct.video.play())
|
||||
await wait(() => window.direct.video.currentTime > 0.3)
|
||||
entry.phase = 'low-group'
|
||||
await page.evaluate(() => {
|
||||
window.direct.hls.currentLevel = 0
|
||||
})
|
||||
@@ -175,19 +180,28 @@ export async function diagnose({ version = '1.7.2', iterations = 5, transport =
|
||||
window.direct.hls.audioTrack = 1
|
||||
})
|
||||
await wait(() => window.direct.records.some(item => item.at >= window.direct.mark && item.event === 'AUDIO_TRACK_SWITCHED' && item.data.id === 1))
|
||||
entry.phase = 'high-group'
|
||||
await page.evaluate(() => {
|
||||
window.direct.hls.currentLevel = 1
|
||||
})
|
||||
await wait(() => window.direct.video.videoHeight === 180 && window.direct.hls.audioTrack === 0)
|
||||
entry.phase = 'commentary-track'
|
||||
await page.evaluate(() => {
|
||||
window.direct.hls.audioTrack = 2
|
||||
})
|
||||
await wait(() => window.direct.records.some(item => item.event === 'AUDIO_TRACK_SWITCHED' && item.data.id === 2))
|
||||
entry.phase = 'return-low-group'
|
||||
await page.evaluate(() => {
|
||||
window.direct.hls.currentLevel = 0
|
||||
})
|
||||
await wait(() => window.direct.hls.audioTracks.length === 2)
|
||||
if (captureBeforeDestroy) {
|
||||
entry.phase = 'capture-before-destroy'
|
||||
entry.beforeDestroy = await page.evaluate(() => ({ coreLoaded: typeof window.Artplayer, pluginLoaded: typeof window.artplayerPluginHlsControl, media: window.direct.state(), sdk: { version: window.Hls.version, workerEnabled: window.direct.hls.config.enableWorker, level: window.direct.hls.currentLevel, audioTrack: window.direct.hls.audioTrack }, events: window.direct.records }))
|
||||
}
|
||||
entry.phase = 'destroy-call'
|
||||
await page.evaluate(() => window.direct.destroy())
|
||||
entry.phase = 'after-destroy-state'
|
||||
await page.evaluate(() => window.direct.state())
|
||||
assert.deepEqual(entry.errors, [])
|
||||
entry.status = 'passed'
|
||||
@@ -198,15 +212,20 @@ export async function diagnose({ version = '1.7.2', iterations = 5, transport =
|
||||
await page.screenshot({ path: path.join(directory, `${iteration}.png`) }).catch(() => {})
|
||||
}
|
||||
finally {
|
||||
entry.failurePhase = entry.status === 'failed' ? entry.phase : undefined
|
||||
entry.phase = 'final-state'
|
||||
entry.state = await page.evaluate(() => ({ coreLoaded: typeof window.Artplayer, pluginLoaded: typeof window.artplayerPluginHlsControl, workers: window.workerEvidence, media: window.direct?.state(), events: window.direct?.records, sdk: { version: window.Hls?.version, level: window.direct?.hls.currentLevel, audioTrack: window.direct?.hls.audioTrack } })).catch(error => ({ error: error.message }))
|
||||
entry.phase = 'trace-stop'
|
||||
await context.tracing.stop({ path: path.join(directory, `${iteration}.zip`) }).catch((error) => {
|
||||
entry.traceError = error.message
|
||||
})
|
||||
entry.phase = 'context-close'
|
||||
await context.close().catch((error) => {
|
||||
entry.closeError = error.message
|
||||
})
|
||||
if (entry.state.error || entry.errors.length || entry.traceError || entry.closeError) {
|
||||
entry.status = 'failed'
|
||||
entry.failurePhase ||= entry.crashes[0]?.phase || (entry.state.error ? 'final-state' : entry.traceError ? 'trace-stop' : 'context-close')
|
||||
entry.failure ||= entry.state.error || entry.traceError || entry.closeError || entry.errors.join('; ')
|
||||
}
|
||||
}
|
||||
@@ -217,14 +236,14 @@ export async function diagnose({ version = '1.7.2', iterations = 5, transport =
|
||||
await browser?.close()
|
||||
server.closeAllConnections()
|
||||
await new Promise(resolve => server.close(resolve))
|
||||
fs.writeFileSync(path.join(directory, 'report.json'), `${JSON.stringify({ version, iterations, transport, teardown, worker, host, plugin, sdkLogs, workerObserver, runnerSHA256, observerSHA256, browserVersion, release, inputs: Object.fromEntries([...files].map(([file, bytes]) => [file, hash(bytes)])), results }, null, 2)}\n`)
|
||||
fs.writeFileSync(path.join(directory, 'report.json'), `${JSON.stringify({ version, iterations, transport, teardown, worker, host, plugin, sdkLogs, workerObserver, captureBeforeDestroy, runnerSHA256, observerSHA256, browserVersion, release, inputs: Object.fromEntries([...files].map(([file, bytes]) => [file, hash(bytes)])), results }, null, 2)}\n`)
|
||||
console.log(`Diagnostic report: ${directory}`)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
const { values } = parseArgs({ options: { 'version': { type: 'string', default: '1.7.2' }, 'iterations': { type: 'string', default: '5' }, 'transport': { type: 'string', default: 'http' }, 'teardown': { type: 'string', default: 'reset-first' }, 'no-worker': { type: 'boolean', default: false }, 'host': { type: 'string', default: 'direct' }, 'plugin': { type: 'boolean', default: false }, 'sdk-logs': { type: 'boolean', default: false }, 'observe-workers': { type: 'boolean', default: false } } })
|
||||
diagnose({ version: values.version, iterations: Number(values.iterations), transport: values.transport, teardown: values.teardown, worker: !values['no-worker'], host: values.host, plugin: values.plugin, sdkLogs: values['sdk-logs'], workerObserver: values['observe-workers'] }).then((results) => {
|
||||
const { values } = parseArgs({ options: { 'version': { type: 'string', default: '1.7.2' }, 'iterations': { type: 'string', default: '5' }, 'transport': { type: 'string', default: 'http' }, 'teardown': { type: 'string', default: 'reset-first' }, 'no-worker': { type: 'boolean', default: false }, 'host': { type: 'string', default: 'direct' }, 'plugin': { type: 'boolean', default: false }, 'sdk-logs': { type: 'boolean', default: false }, 'observe-workers': { type: 'boolean', default: false }, 'capture-before-destroy': { type: 'boolean', default: false } } })
|
||||
diagnose({ version: values.version, iterations: Number(values.iterations), transport: values.transport, teardown: values.teardown, worker: !values['no-worker'], host: values.host, plugin: values.plugin, sdkLogs: values['sdk-logs'], workerObserver: values['observe-workers'], captureBeforeDestroy: values['capture-before-destroy'] }).then((results) => {
|
||||
process.exitCode = results.some(result => result.status !== 'passed') ? 1 : 0
|
||||
}).catch((error) => {
|
||||
console.error(error)
|
||||
|
||||
+3
-1
@@ -2100,7 +2100,9 @@
|
||||
"evidence": [
|
||||
"changes/2026-09-12-PKG-HLS-SDK-01-integration.md",
|
||||
"baselines/hls-sdk-validation.json",
|
||||
"baselines/hls-sdk-diagnostics.json"
|
||||
"baselines/hls-sdk-diagnostics.json",
|
||||
"changes/2026-09-14-PKG-HLS-SDK-01-http-teardown.md",
|
||||
"baselines/hls-http-teardown-validation.json"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user