fix(electron): re-probe mpv after a late login shell PATH either way

A Linux mpv probe that ran on the inherited PATH can be wrong in both
directions: the login shell PATH may add mpv or drop the directory the
inherited one found it in. forgetLinuxMpvExecutableProbe() now clears a
found result as well as a missing one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-10-03 09:13:04 +02:00
1 parent bb172fa6d8
commit e60a65b3d0
4 files changed
+17 -17

No files matched your search

@@ -9,7 +9,7 @@ const mockEmbeddedMpvService = {
prepareAddon: jest.fn(),
getSupport: jest.fn(),
willProbeLinuxMpvExecutable: jest.fn(() => false),
forgetMissingLinuxMpvExecutable: jest.fn(),
forgetLinuxMpvExecutableProbe: jest.fn(),
setPaused: jest.fn(),
};
const mockSessionOptions = {
@@ -108,12 +108,12 @@ describe('EmbeddedMpvEvents IPC handlers', () => {
settle(true);
await expect(support).resolves.toEqual({ supported: true });
expect(
mockEmbeddedMpvService.forgetMissingLinuxMpvExecutable
mockEmbeddedMpvService.forgetLinuxMpvExecutableProbe
).not.toHaveBeenCalled();
}
);
it('re-probes a missing mpv once a lookup that ran out finally answers', async () => {
it('re-probes mpv once a lookup that ran out finally answers', async () => {
mockEmbeddedMpvService.willProbeLinuxMpvExecutable.mockReturnValue(
true
);
@@ -126,13 +126,13 @@ describe('EmbeddedMpvEvents IPC handlers', () => {
getIpcMainHandler(EMBEDDED_MPV_SUPPORT)({})
).resolves.toEqual({ supported: false });
expect(
mockEmbeddedMpvService.forgetMissingLinuxMpvExecutable
mockEmbeddedMpvService.forgetLinuxMpvExecutableProbe
).not.toHaveBeenCalled();
settleLookup();
await new Promise<void>((resolve) => setImmediate(resolve));
expect(
mockEmbeddedMpvService.forgetMissingLinuxMpvExecutable
mockEmbeddedMpvService.forgetLinuxMpvExecutableProbe
).toHaveBeenCalledTimes(1);
});
@@ -81,10 +81,10 @@ async function afterLoginShellPathIfProbing<T>(check: () => T): Promise<T> {
return check();
}
// The lookup ran out of budget, so this probe sees the inherited PATH.
// Once the shell does answer, a "missing" result is probed again.
// Once the shell does answer, the result is probed again.
const result = check();
void whenLoginShellPathSettled().then(() =>
getService().forgetMissingLinuxMpvExecutable()
getService().forgetLinuxMpvExecutableProbe()
);
return result;
}
@@ -394,7 +394,7 @@ describe('EmbeddedMpvNativeService power blocker', () => {
expect(service.willProbeLinuxMpvExecutable()).toBe(false);
});
it('probes a missing mpv again after it is forgotten, but keeps a found one', () => {
it('probes mpv again after a missing or a found result is forgotten', () => {
Object.defineProperty(process, 'platform', { value: 'linux' });
process.env.DISPLAY = ':0';
delete process.env.WAYLAND_DISPLAY;
@@ -403,14 +403,15 @@ describe('EmbeddedMpvNativeService power blocker', () => {
mockRuntimeUsable();
expect(service.getSupport().supported).toBe(false);
service.forgetMissingLinuxMpvExecutable();
service.forgetLinuxMpvExecutableProbe();
expect(service.willProbeLinuxMpvExecutable()).toBe(true);
mockSpawnSync.mockReturnValue({ status: 0 });
service.getSupport();
expect(mockSpawnSync).toHaveBeenCalledTimes(2);
service.forgetMissingLinuxMpvExecutable();
expect(service.willProbeLinuxMpvExecutable()).toBe(false);
service.forgetLinuxMpvExecutableProbe();
expect(service.willProbeLinuxMpvExecutable()).toBe(true);
});
it('predicts no probe for the frame-copy engine or native Wayland', () => {
@@ -394,14 +394,13 @@ export class EmbeddedMpvNativeService {
}
/**
* Drops a cached "mpv missing" result, so the next support check probes
* again (a found mpv stays cached). For a probe that ran before the
* login shell PATH arrived.
* Drops the cached `mpv --version` result, found or missing, so the next
* support check probes again. For a probe that ran before the login
* shell PATH arrived: that PATH may add mpv or leave out the directory
* the inherited one found it in.
*/
forgetMissingLinuxMpvExecutable(): void {
if (this.cachedLinuxMpvExecutableReason) {
this.cachedLinuxMpvExecutableReason = undefined;
}
forgetLinuxMpvExecutableProbe(): void {
this.cachedLinuxMpvExecutableReason = undefined;
}
getSupport(): EmbeddedMpvSupport {