Consider this snippet:
async function ClumsyFunc(constraints) {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
if (SomeCondition()) {
HandOff(stream);
}
// Oops! Dropped last reference on the floor. What a mess...
}
What happens now? Should the stream and its tracks be eligible for garbage collection? If so, there are user-facing side-effects.
- Camera/mic hardware indicator goes off.
- User agent indicators disappear.
- OS-level indicators disappear.
Note that getDisplayMedia has similar issues. In some implementations (Chromium), an application could even heuristically observed GC this way, because tab-sharing adds an infobar that affects the viewport's size, and when it disappears the viewport changes back.
So should GC of live tracks be disallowed? Allowed? Encouraged?
Arguments for allowing GC:
- Reduce CPU and battery consumption.
- Free up the hardware, for use by other apps with a different configuration.
- Inform the user of reality - nobody is reading their mic/camera/screen anymore.
Argument for disallowing GC:
- The app should have stopped the track first. Relying on GC creates an unpredictable user experience. By suppressing GC, we'll expose the bug and motivate the app devs to fix it, which is better for users - our top constituency.
- Garbage-collecting live tracks allows apps to heuristically observe GC (see above).
Consider this snippet:
What happens now? Should the stream and its tracks be eligible for garbage collection? If so, there are user-facing side-effects.
Note that getDisplayMedia has similar issues. In some implementations (Chromium), an application could even heuristically observed GC this way, because tab-sharing adds an infobar that affects the viewport's size, and when it disappears the viewport changes back.
So should GC of live tracks be disallowed? Allowed? Encouraged?
Arguments for allowing GC:
Argument for disallowing GC: