MV3 dev dynamic content script registration drops matchOriginAsFallback
#2.335 aberto em 4 de mai. de 2026
Métricas do repositório
- Stars
- (9.861 stars)
- Métricas de merge de PR
- (Mesclagem média 11d 22h) (51 fundiu PRs em 30d)
Description
Describe the bug
In MV3 development mode, WXT dynamically registers content scripts from the background service worker instead of putting them in manifest.content_scripts.
When a content script is defined with matchOriginAsFallback: true, the production manifest preserves the option as match_origin_as_fallback: true, but the dev-mode dynamic registration drops it. As a result, dev mode behaves differently from production for about:blank / about:srcdoc iframes that depend on origin fallback.
Reproduction
Define a content script like this:
export default defineContentScript({
matches: ["*://*/*", "file:///*"],
allFrames: true,
matchAboutBlank: true,
matchOriginAsFallback: true,
async main() {
// ...
},
})
Run WXT in MV3 dev mode:
wxt -b edge
Then inspect the registered content scripts from the extension service worker:
await chrome.scripting.getRegisteredContentScripts()
Actual behavior
The dynamically registered content script has matchOriginAsFallback: false:
{
"id": "wxt:content-scripts/node-trigger.js",
"js": ["content-scripts/node-trigger.js"],
"matches": ["*://*/*", "file:///*"],
"allFrames": true,
"matchOriginAsFallback": false,
"runAt": "document_idle",
"world": "ISOLATED"
}
This prevents the content script from running in a TinyMCE editor iframe whose document is about:srcdoc, even though that same script works in production.
Expected behavior
The dev-mode dynamic registration should preserve matchOriginAsFallback: true:
{
"id": "wxt:content-scripts/node-trigger.js",
"js": ["content-scripts/node-trigger.js"],
"matches": ["*://*/*", "file:///*"],
"allFrames": true,
"matchOriginAsFallback": true,
"runAt": "document_idle",
"world": "ISOLATED"
}
Production build already emits the expected static manifest fields:
{
"matches": ["*://*/*", "file:///*"],
"all_frames": true,
"match_about_blank": true,
"js": ["content-scripts/node-trigger.js"],
"match_origin_as_fallback": true
}
Likely cause
In mapWxtOptionsToContentScript, WXT maps:
match_origin_as_fallback: options.matchOriginAsFallback
But mapWxtOptionsToRegisteredContentScript does not map the equivalent dynamic registration field:
function mapWxtOptionsToRegisteredContentScript(options, js, css) {
return {
allFrames: options.allFrames,
excludeMatches: options.excludeMatches,
matches: options.matches,
runAt: options.runAt,
js,
css,
world: options.world
};
}
Adding matchOriginAsFallback: options.matchOriginAsFallback to the dynamic registration payload fixes the dev-mode behavior in my testing.
Notes
In my Edge MV3 dev testing, chrome.scripting.registerContentScripts accepted matchOriginAsFallback, and that was enough for the about:srcdoc iframe case. Passing matchAboutBlank to dynamic registration appeared to make registration fail, so this report is specifically about preserving matchOriginAsFallback for dev-mode dynamic content script registration.
Environment
- WXT:
0.20.25 - Browser target:
edge-mv3 - Mode: development (
wxt -b edge) *** End Patch