diff --git a/packages/wxt-demo/src/entrypoints/content.ts b/packages/wxt-demo/src/entrypoints/content.ts index 1b3865ba3..6672c36a4 100644 --- a/packages/wxt-demo/src/entrypoints/content.ts +++ b/packages/wxt-demo/src/entrypoints/content.ts @@ -2,6 +2,7 @@ export default defineContentScript({ matches: ['*://*.example.com/*'], async main() { + console.log(getAppConfig()); console.log('Injecting...'); await injectScript('/unlisted.js', { keepInDom: true, diff --git a/packages/wxt/src/core/utils/create-file-reloader.ts b/packages/wxt/src/core/utils/create-file-reloader.ts index 1a731e245..b1d7c242e 100644 --- a/packages/wxt/src/core/utils/create-file-reloader.ts +++ b/packages/wxt/src/core/utils/create-file-reloader.ts @@ -124,6 +124,9 @@ export function createFileReloader(server: WxtDevServer) { // Perform reloads if (hasNewEntrypoints || changes.type === 'extension-reload') { + // `server.reloadExtension()` only reloads the background/manifest + // reload content scripts into tabs which are already open. + reloadContentScripts(newOutput.steps, server); server.reloadExtension(); wxt.logger.success(`Reloaded extension`); } else if (changes.type === 'html-reload') { diff --git a/packages/wxt/src/utils/internal/dev-server-websocket.ts b/packages/wxt/src/utils/internal/dev-server-websocket.ts index 913f6b7e2..4b5943ae2 100644 --- a/packages/wxt/src/utils/internal/dev-server-websocket.ts +++ b/packages/wxt/src/utils/internal/dev-server-websocket.ts @@ -1,3 +1,4 @@ +import type { Browser } from '@wxt-dev/browser'; import { logger } from './logger'; interface WebSocketMessage { @@ -76,5 +77,6 @@ export interface ReloadContentScriptPayload { matches: string[]; js?: string[]; css?: string[]; + world?: Browser.scripting.RegisteredContentScript['world']; }; } diff --git a/packages/wxt/src/virtual/background-entrypoint.ts b/packages/wxt/src/virtual/background-entrypoint.ts index b0206e0bb..41e13ee8f 100644 --- a/packages/wxt/src/virtual/background-entrypoint.ts +++ b/packages/wxt/src/virtual/background-entrypoint.ts @@ -4,12 +4,17 @@ import { getDevServerWebSocket } from '../utils/internal/dev-server-websocket'; import { logger } from '../utils/internal/logger'; import { browser } from 'wxt/browser'; import { keepServiceWorkerAlive } from './utils/keep-service-worker-alive'; -import { reloadContentScript } from './utils/reload-content-scripts'; +import { + reloadContentScript, + waitForPendingContentScriptReloads, +} from './utils/reload-content-scripts'; if (import.meta.env.COMMAND === 'serve') { try { const ws = getDevServerWebSocket(); - ws.addWxtEventListener('wxt:reload-extension', () => { + ws.addWxtEventListener('wxt:reload-extension', async () => { + // Wait for content script reloads to finish before killing the background. + await waitForPendingContentScriptReloads(); browser.runtime.reload(); }); ws.addWxtEventListener('wxt:reload-content-script', (event) => { diff --git a/packages/wxt/src/virtual/utils/reload-content-scripts.ts b/packages/wxt/src/virtual/utils/reload-content-scripts.ts index 5d3b4363e..fc2de21e5 100644 --- a/packages/wxt/src/virtual/utils/reload-content-scripts.ts +++ b/packages/wxt/src/virtual/utils/reload-content-scripts.ts @@ -3,13 +3,20 @@ import { logger } from '../../utils/internal/logger'; import { MatchPattern } from 'wxt/utils/match-patterns'; import type { ReloadContentScriptPayload } from '../../utils/internal/dev-server-websocket'; -export function reloadContentScript(payload: ReloadContentScriptPayload) { +const pendingReloads = new Set>(); + +export function reloadContentScript(payload: ReloadContentScriptPayload): void { const manifest = browser.runtime.getManifest(); - if (manifest.manifest_version == 2) { - void reloadContentScriptMv2(payload); - } else { - void reloadContentScriptMv3(payload); - } + const promise = + manifest.manifest_version == 2 + ? reloadContentScriptMv2(payload) + : reloadContentScriptMv3(payload); + pendingReloads.add(promise); + promise.finally(() => pendingReloads.delete(promise)); +} + +export async function waitForPendingContentScriptReloads(): Promise { + await Promise.allSettled(pendingReloads); } export async function reloadContentScriptMv3({ @@ -96,7 +103,11 @@ async function reloadTabsForContentScript(contentScript: ContentScript) { await Promise.all( matchingTabs.map(async (tab) => { try { - await browser.tabs.reload(tab.id!); + await browser.scripting.executeScript({ + target: { tabId: tab.id! }, + files: contentScript.js!, + world: contentScript.world, + }); } catch (err) { logger.warn('Failed to reload tab:', err); }