Prerequisites
I tried to reproduce the issue when...
Description
In Chromium-based browsers, browser.tabs.executeScript returns undefined instead of a Promise when no callback is supplied. This causes uncaught exceptions when chaining .catch() directly onto the execution block within js/vapi-scripting.js.
The first error triggers immediately upon extension installation, and the second one triggers whenever any website is opened.
A specific URL where the issue occurs.
Affects extension background context globally, not web pages.
Steps to Reproduce
- Load unpacked uBO release in Chromium with a standard 3-part production version string (which unsets devbuild flags in vapi-common.js).
- Observe immediate crash in background console.
- Open any website (e.g., https://www.google.com/) and observe the second crash.
Expected behavior
Script injections should handle injection errors via a standard callback with browser.runtime.lastError checking instead of assuming a Promise return in Chromium MV2 environments.
Troubleshooting information
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'catch')
Context: background.html
Stack trace: js/vapi-scripting.js:83 (anonymous function)
Error in event handler: TypeError: Cannot read properties of undefined (reading 'catch')
Context: background.html
Stack trace: js/vapi-scripting.js:109 (anonymous function)
uBlock Origin: 1.75.1b9
Chromium: 150
filterset (summary):
network: 253909
cosmetic: 47620
scriptlet: 38498
html: 0
listset (total-discarded, last-updated):
default:
user-filters: 0-0, never
ublock-filters: 54057-114, never
ublock-badware: 10374-17, never
ublock-privacy: 4168-2, never
ublock-unbreak: 2837-0, never
ublock-quick-fixes: 643-0, never
easylist: 88129-647, never
easyprivacy: 56811-774, never
urlhaus-1: 113612-3, never
plowe-0: 3547-3, never
filterset (user): [empty]
userSettings: [none]
hiddenSettings: [none]
supportStats:
allReadyAfter: 14743 ms
maxAssetCacheWait: 29 ms
cacheBackend: indexedDB
Proposed Fix
Replacing .catch() with a callback that references browser.runtime.lastError solves the issue in Chromium:
let onceFn = async () => {
if ( Boolean(contentScriptCode) === false ) { return; }
const tabs = await vAPI.tabs.query({ url: '<all_urls>' });
for ( const tab of tabs ) {
if ( tab.discarded === true ) { continue; }
if ( tab.status === 'unloaded' ) { continue; }
browser.tabs.executeScript(tab.id, {
allFrames: true,
matchAboutBlank: true,
runAt: 'document_start',
code: contentScriptCode,
}, () => {
// Suppress injection errors on restricted or privileged pages
void browser.runtime.lastError;
});
}
};
browser.webNavigation.onCommitted.addListener(details => {
if ( /^https?:|^about:/.test(details.url) === false ) { return; }
if ( Boolean(contentScriptCode) === false ) { return; }
browser.tabs.executeScript(details.tabId, {
frameId: details.frameId,
matchAboutBlank: true,
runAt: 'document_start',
code: contentScriptCode,
}, () => {
// Suppress injection errors
void browser.runtime.lastError;
});
});
Prerequisites
I tried to reproduce the issue when...
Description
In Chromium-based browsers, browser.tabs.executeScript returns undefined instead of a Promise when no callback is supplied. This causes uncaught exceptions when chaining .catch() directly onto the execution block within js/vapi-scripting.js.
The first error triggers immediately upon extension installation, and the second one triggers whenever any website is opened.
A specific URL where the issue occurs.
Affects extension background context globally, not web pages.Steps to Reproduce
Expected behavior
Script injections should handle injection errors via a standard callback with browser.runtime.lastError checking instead of assuming a Promise return in Chromium MV2 environments.
Troubleshooting information
Proposed Fix
Replacing
.catch()with a callback that referencesbrowser.runtime.lastErrorsolves the issue in Chromium: