From 083e5e1168540eed6844be20b02e2d9cb7f86483 Mon Sep 17 00:00:00 2001 From: Max Freedom Pollard <272618364+MaxFreedomPollard@users.noreply.github.com> Date: Sat, 12 Sep 2026 15:00:01 -0400 Subject: [PATCH] fix(chromium): Fixed silent reload failures on Chrome 125 and earlier Reloading an extension on Chrome 125 and earlier printed "Last extension reload" even when the reload had not happened, and a failure inside the reload ended the web-ext process on an unhandled rejection instead of logging the usual reload error. reloadAllExtensions called reloadAllExtensionsFallbackForChrome125andEarlier without awaiting it, so the returned promise was dropped. The method wrote the success line and resolved with a plain result while the reload was still pending, which left any rejection with nowhere to go and kept it away from MultiExtensionRunner.handleReloadResults. Adding the await lets it propagate into the existing reloadError plumbing. --- src/extension-runners/chromium.js | 2 +- .../test-extension-runners/test.chromium.js | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/extension-runners/chromium.js b/src/extension-runners/chromium.js index f04faff69a..4ee60d5e75 100644 --- a/src/extension-runners/chromium.js +++ b/src/extension-runners/chromium.js @@ -395,7 +395,7 @@ export class ChromiumExtensionRunner { const runnerName = this.getName(); if (this.forceUseDeprecatedLoadExtension) { - this.reloadAllExtensionsFallbackForChrome125andEarlier(); + await this.reloadAllExtensionsFallbackForChrome125andEarlier(); } else { for (const { sourceDir } of this.params.extensions) { try { diff --git a/tests/unit/test-extension-runners/test.chromium.js b/tests/unit/test-extension-runners/test.chromium.js index 3f0cc7b37f..df88aa70d5 100644 --- a/tests/unit/test-extension-runners/test.chromium.js +++ b/tests/unit/test-extension-runners/test.chromium.js @@ -624,6 +624,39 @@ describe('util/extension-runners/chromium', async () => { sinon.assert.calledOnce(fakeChromeInstance.kill); }); + it('rejects when reloading fails (old Chrome)', async () => { + const { params } = prepareExtensionRunnerParams( + {}, + { loadUnpackedUnsupported: true }, + ); + const runnerInstance = new ChromiumExtensionRunner(params); + + await runnerInstance.run(); + assert.isTrue(runnerInstance.forceUseDeprecatedLoadExtension); + + sinon + .stub(runnerInstance.cdp, 'sendCommand') + .rejects(new Error('CDP failure')); + const stdoutSpy = sinon.spy(process.stdout, 'write'); + + try { + await assert.isRejected( + runnerInstance.reloadAllExtensions(), + /CDP failure/, + ); + assert.isFalse( + stdoutSpy.getCalls().some((call) => { + return String(call.args[0]).includes('Last extension reload'); + }), + 'expected no reload success message when the reload failed', + ); + } finally { + stdoutSpy.restore(); + } + + await runnerInstance.exit(); + }); + describe('getPrefs', () => { it('merges default and custom preferences from an object and passes them to the launcher', async () => { const { params } = prepareExtensionRunnerParams({