MV3 dev dynamic content script registration drops matchOriginAsFallback
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 10.5k
- Forks
- 564
- PR merge metrics
- No merged PRs in 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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Locate mapWxtOptionsToRegisteredContentScript and compare its fields with mapWxtOptionsToContentScript. Preserve matchOriginAsFallback in the dynamic registration payload, then verify that MV3 development registration retains true for the provided content-script configuration and does not regress production behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100