@amazon/vinyl 4.0.1-next.20261017024550 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +14 -7
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +14 -7
- package/dist/index.js.map +2 -2
- package/dist/test/integ.es5.js +131 -131
- package/dist/test/integ.js +54 -8
- package/dist/test/integ.js.map +2 -2
- package/dist/types/current/playback/createStallMonitor.d.ts +11 -6
- package/dist/types/current/playback/createStallMonitor.d.ts.map +1 -1
- package/dist/types/current/playback/createStallMonitor.js +29 -11
- package/dist/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ts3.7/playback/createStallMonitor.d.ts +11 -6
- package/dist/types/ts4.1/playback/createStallMonitor.d.ts +11 -6
- package/dist/types/ts4.7/playback/createStallMonitor.d.ts +11 -6
- package/dist/unit/types/current/playback/createStallMonitor.test.js +43 -1
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
|
@@ -3,8 +3,8 @@ import type { ReadonlyPlaybackController } from './ReadonlyPlaybackController';
|
|
|
3
3
|
import { StallEndedReason } from './ReadonlyPlaybackController';
|
|
4
4
|
export interface StallMonitorOptions {
|
|
5
5
|
/**
|
|
6
|
-
* Seconds the play head must be frozen (
|
|
7
|
-
* reported. Default: 1
|
|
6
|
+
* Seconds the play head must be frozen (`currentTime` not advancing) while playing before a
|
|
7
|
+
* stall is reported. Default: 1
|
|
8
8
|
*/
|
|
9
9
|
readonly stallThreshold?: number;
|
|
10
10
|
/**
|
|
@@ -13,7 +13,7 @@ export interface StallMonitorOptions {
|
|
|
13
13
|
readonly pollInterval?: number;
|
|
14
14
|
}
|
|
15
15
|
export interface StallEndedInfo {
|
|
16
|
-
/** Time of the last
|
|
16
|
+
/** Time of the last progress observed before the play head froze. */
|
|
17
17
|
readonly started: Timestamp;
|
|
18
18
|
/** Time the stall ended. */
|
|
19
19
|
readonly ended: Timestamp;
|
|
@@ -30,14 +30,19 @@ export interface StallMonitorCallbacks {
|
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Watches a {@link ReadonlyPlaybackController} for stalls while playing: the play head freezing
|
|
33
|
-
* (
|
|
33
|
+
* (`currentTime` not advancing) for longer than {@link StallMonitorOptions.stallThreshold} seconds.
|
|
34
|
+
*
|
|
35
|
+
* Progress is observed both from `timeUpdate` events and by reading `currentTime` on each poll. A
|
|
36
|
+
* late `timeUpdate` alone is not a stall: when the main thread is busy (a long task, a GC pause) or
|
|
37
|
+
* event delivery is delayed, the play head keeps advancing while no `timeUpdate` reaches script,
|
|
38
|
+
* and the poll sees that advance rather than reporting a freeze.
|
|
34
39
|
*
|
|
35
40
|
* Detection only runs once playback has actually been observed (a `playing` event) and is
|
|
36
41
|
* suspended on `pause`/`seeking`/`emptied` until playback is observed again — so a stall is never
|
|
37
42
|
* reported during initial loading or while awaiting a seek. A detected stall ends when the play
|
|
38
43
|
* head advances again (`playing`) or playback stops for another reason (`pause`/`seeking`/
|
|
39
|
-
* `emptied`); {@link StallEndedInfo.duration} is measured from the last
|
|
40
|
-
* freeze, so it reflects the full frozen time rather than only the time past the threshold.
|
|
44
|
+
* `emptied`); {@link StallEndedInfo.duration} is measured from the last observed progress before
|
|
45
|
+
* the freeze, so it reflects the full frozen time rather than only the time past the threshold.
|
|
41
46
|
*
|
|
42
47
|
* Returns a function that stops the monitor.
|
|
43
48
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStallMonitor.d.ts","sourceRoot":"","sources":["../../../../src/playback/createStallMonitor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,MAAM,WAAW,mBAAmB;IAChC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,cAAc;IAC3B,
|
|
1
|
+
{"version":3,"file":"createStallMonitor.d.ts","sourceRoot":"","sources":["../../../../src/playback/createStallMonitor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,MAAM,WAAW,mBAAmB;IAChC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,cAAc;IAC3B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAA;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;CACpC;AAED,MAAM,WAAW,qBAAqB;IAClC,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAA;IACnC,yCAAyC;IACzC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;CACxD;AASD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAC9B,UAAU,EAAE,0BAA0B,EACtC,SAAS,EAAE,qBAAqB,EAChC,OAAO,GAAE,mBAAwB,GAClC,MAAM,IAAI,CA8FZ"}
|
|
@@ -12,24 +12,29 @@ import { StallEndedReason } from './ReadonlyPlaybackController';
|
|
|
12
12
|
const PROGRESS_EPSILON = 1e-6;
|
|
13
13
|
/**
|
|
14
14
|
* Watches a {@link ReadonlyPlaybackController} for stalls while playing: the play head freezing
|
|
15
|
-
* (
|
|
15
|
+
* (`currentTime` not advancing) for longer than {@link StallMonitorOptions.stallThreshold} seconds.
|
|
16
|
+
*
|
|
17
|
+
* Progress is observed both from `timeUpdate` events and by reading `currentTime` on each poll. A
|
|
18
|
+
* late `timeUpdate` alone is not a stall: when the main thread is busy (a long task, a GC pause) or
|
|
19
|
+
* event delivery is delayed, the play head keeps advancing while no `timeUpdate` reaches script,
|
|
20
|
+
* and the poll sees that advance rather than reporting a freeze.
|
|
16
21
|
*
|
|
17
22
|
* Detection only runs once playback has actually been observed (a `playing` event) and is
|
|
18
23
|
* suspended on `pause`/`seeking`/`emptied` until playback is observed again — so a stall is never
|
|
19
24
|
* reported during initial loading or while awaiting a seek. A detected stall ends when the play
|
|
20
25
|
* head advances again (`playing`) or playback stops for another reason (`pause`/`seeking`/
|
|
21
|
-
* `emptied`); {@link StallEndedInfo.duration} is measured from the last
|
|
22
|
-
* freeze, so it reflects the full frozen time rather than only the time past the threshold.
|
|
26
|
+
* `emptied`); {@link StallEndedInfo.duration} is measured from the last observed progress before
|
|
27
|
+
* the freeze, so it reflects the full frozen time rather than only the time past the threshold.
|
|
23
28
|
*
|
|
24
29
|
* Returns a function that stops the monitor.
|
|
25
30
|
*/
|
|
26
31
|
export function createStallMonitor(controller, callbacks, options = {}) {
|
|
27
32
|
const stallThresholdMs = (options.stallThreshold ?? 1) * 1000;
|
|
28
33
|
const pollIntervalMs = (options.pollInterval ?? 0.25) * 1000;
|
|
29
|
-
//
|
|
30
|
-
let observedPlaying = false;
|
|
31
|
-
// Wall-clock time of the last `timeUpdate` — the reference start of any freeze.
|
|
34
|
+
// Wall-clock time of the last observed progress — the reference start of any freeze.
|
|
32
35
|
let lastProgressAt = Date.now();
|
|
36
|
+
// Play head position at the last observed progress.
|
|
37
|
+
let lastProgressPosition = controller.currentTime;
|
|
33
38
|
let inStall = false;
|
|
34
39
|
let pollId = null;
|
|
35
40
|
const { add, dispose } = createDisposer();
|
|
@@ -52,11 +57,26 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
52
57
|
pollId = null;
|
|
53
58
|
};
|
|
54
59
|
add(stopPoll);
|
|
60
|
+
const markProgress = () => {
|
|
61
|
+
lastProgressAt = Date.now();
|
|
62
|
+
lastProgressPosition = controller.currentTime;
|
|
63
|
+
};
|
|
55
64
|
const startPoll = () => {
|
|
56
65
|
if (pollId != null)
|
|
57
66
|
return;
|
|
67
|
+
// Polls only while playback is observed — started on `playing`, stopped by `suspend` —
|
|
68
|
+
// which gates out initial load and post-seek buffering.
|
|
58
69
|
pollId = setInterval(() => {
|
|
59
|
-
|
|
70
|
+
// The play head advanced without a `timeUpdate` reaching us yet (e.g. a long task
|
|
71
|
+
// delayed it past this poll): that's progress, not a freeze.
|
|
72
|
+
if (controller.currentTime - lastProgressPosition >
|
|
73
|
+
PROGRESS_EPSILON) {
|
|
74
|
+
if (inStall)
|
|
75
|
+
endStall(StallEndedReason.PLAYING);
|
|
76
|
+
markProgress();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (inStall)
|
|
60
80
|
return;
|
|
61
81
|
if (Date.now() - lastProgressAt >= stallThresholdMs) {
|
|
62
82
|
inStall = true;
|
|
@@ -68,7 +88,6 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
68
88
|
// playback is observed again.
|
|
69
89
|
const suspend = (reason) => {
|
|
70
90
|
endStall(reason);
|
|
71
|
-
observedPlaying = false;
|
|
72
91
|
stopPoll();
|
|
73
92
|
};
|
|
74
93
|
add(controller.on('playing', () => {
|
|
@@ -78,8 +97,7 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
78
97
|
// Whether resuming or freshly starting, the play head is advancing again, so restart the
|
|
79
98
|
// freeze clock. Without this the poll could immediately re-detect a stall from the stale
|
|
80
99
|
// pre-freeze timestamp before the first post-resume `timeUpdate` resets it.
|
|
81
|
-
|
|
82
|
-
observedPlaying = true;
|
|
100
|
+
markProgress();
|
|
83
101
|
startPoll();
|
|
84
102
|
}));
|
|
85
103
|
add(controller.on('timeUpdate', ({ previous, current }) => {
|
|
@@ -90,7 +108,7 @@ export function createStallMonitor(controller, callbacks, options = {}) {
|
|
|
90
108
|
// The play head advanced: close any open stall, then reset the freeze clock.
|
|
91
109
|
if (inStall)
|
|
92
110
|
endStall(StallEndedReason.PLAYING);
|
|
93
|
-
|
|
111
|
+
markProgress();
|
|
94
112
|
}));
|
|
95
113
|
add(controller.on('pause', () => suspend(StallEndedReason.PAUSE)));
|
|
96
114
|
add(controller.on('seeking', () => suspend(StallEndedReason.SEEKING)));
|