wxt 0.20.13 → 0.20.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/dist/browser.d.mts +20 -0
  2. package/dist/browser.mjs +18 -3
  3. package/dist/builtin-modules/index.mjs +7 -2
  4. package/dist/builtin-modules/unimport.mjs +69 -75
  5. package/dist/cli/cli-utils.mjs +54 -50
  6. package/dist/cli/commands.mjs +78 -103
  7. package/dist/cli/index.d.mts +1 -0
  8. package/dist/cli/index.mjs +9 -4
  9. package/dist/core/{build.d.ts → build.d.mts} +6 -2
  10. package/dist/core/build.mjs +23 -4
  11. package/dist/core/builders/vite/index.mjs +293 -343
  12. package/dist/core/builders/vite/plugins/bundleAnalysis.mjs +11 -12
  13. package/dist/core/builders/vite/plugins/cssEntrypoints.mjs +27 -20
  14. package/dist/core/builders/vite/plugins/defineImportMeta.mjs +17 -12
  15. package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +105 -136
  16. package/dist/core/builders/vite/plugins/devServerGlobals.mjs +15 -14
  17. package/dist/core/builders/vite/plugins/download.mjs +23 -12
  18. package/dist/core/builders/vite/plugins/entrypointGroupGlobals.mjs +18 -14
  19. package/dist/core/builders/vite/plugins/extensionApiMock.mjs +31 -33
  20. package/dist/core/builders/vite/plugins/globals.mjs +14 -13
  21. package/dist/core/builders/vite/plugins/iifeFooter.mjs +17 -11
  22. package/dist/core/builders/vite/plugins/index.mjs +18 -16
  23. package/dist/core/builders/vite/plugins/noopBackground.mjs +21 -15
  24. package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.mjs +26 -23
  25. package/dist/core/builders/vite/plugins/resolveAppConfig.mjs +26 -24
  26. package/dist/core/builders/vite/plugins/resolveVirtualModules.mjs +28 -26
  27. package/dist/core/builders/vite/plugins/tsconfigPaths.mjs +11 -11
  28. package/dist/core/builders/vite/plugins/wxtPluginLoader.mjs +42 -47
  29. package/dist/core/{clean.d.ts → clean.d.mts} +7 -3
  30. package/dist/core/clean.mjs +38 -35
  31. package/dist/core/{create-server.d.ts → create-server.d.mts} +6 -2
  32. package/dist/core/create-server.mjs +236 -247
  33. package/dist/core/define-config.d.mts +6 -0
  34. package/dist/core/define-config.mjs +6 -2
  35. package/dist/core/define-web-ext-config.d.mts +13 -0
  36. package/dist/core/define-web-ext-config.mjs +16 -7
  37. package/dist/core/generate-wxt-dir.mjs +110 -148
  38. package/dist/core/index.d.mts +9 -0
  39. package/dist/core/index.mjs +12 -8
  40. package/dist/core/initialize.d.mts +8 -0
  41. package/dist/core/initialize.mjs +110 -124
  42. package/dist/core/keyboard-shortcuts.mjs +30 -28
  43. package/dist/core/package-managers/bun.mjs +18 -16
  44. package/dist/core/package-managers/deno.mjs +12 -8
  45. package/dist/core/package-managers/index.mjs +52 -60
  46. package/dist/core/package-managers/npm.mjs +51 -52
  47. package/dist/core/package-managers/pnpm.mjs +21 -18
  48. package/dist/core/package-managers/yarn.mjs +31 -28
  49. package/dist/core/prepare.d.mts +6 -0
  50. package/dist/core/prepare.mjs +12 -7
  51. package/dist/core/resolve-config.mjs +393 -462
  52. package/dist/core/runners/index.mjs +15 -10
  53. package/dist/core/runners/manual.mjs +13 -14
  54. package/dist/core/runners/safari.mjs +13 -14
  55. package/dist/core/runners/web-ext.mjs +62 -83
  56. package/dist/core/runners/wsl.mjs +13 -14
  57. package/dist/core/utils/arrays.mjs +23 -12
  58. package/dist/core/utils/building/build-entrypoints.mjs +44 -40
  59. package/dist/core/utils/building/detect-dev-changes.mjs +84 -105
  60. package/dist/core/utils/building/find-entrypoints.mjs +278 -359
  61. package/dist/core/utils/building/group-entrypoints.mjs +42 -35
  62. package/dist/core/utils/building/index.mjs +8 -6
  63. package/dist/core/utils/building/internal-build.mjs +86 -102
  64. package/dist/core/utils/building/rebuild.mjs +50 -30
  65. package/dist/core/utils/cache.mjs +29 -18
  66. package/dist/core/utils/constants.mjs +9 -1
  67. package/dist/core/utils/content-scripts.mjs +56 -54
  68. package/dist/core/utils/content-security-policy.mjs +36 -39
  69. package/dist/core/utils/entrypoints.mjs +51 -28
  70. package/dist/core/utils/env.mjs +22 -17
  71. package/dist/core/utils/environments/browser-environment.mjs +13 -12
  72. package/dist/core/utils/environments/environment.mjs +36 -33
  73. package/dist/core/utils/environments/extension-environment.mjs +15 -10
  74. package/dist/core/utils/environments/index.mjs +4 -2
  75. package/dist/core/utils/eslint.mjs +11 -10
  76. package/dist/core/utils/fs.mjs +23 -11
  77. package/dist/core/utils/globals.mjs +53 -51
  78. package/dist/core/utils/i18n.mjs +41 -32
  79. package/dist/core/utils/index.mjs +3 -0
  80. package/dist/core/utils/log/index.mjs +6 -4
  81. package/dist/core/utils/log/printBuildSummary.mjs +20 -25
  82. package/dist/core/utils/log/printFileList.mjs +30 -33
  83. package/dist/core/utils/log/printHeader.mjs +9 -5
  84. package/dist/core/utils/log/printTable.mjs +19 -21
  85. package/dist/core/utils/manifest.mjs +366 -479
  86. package/dist/core/utils/minimatch-multiple.mjs +26 -15
  87. package/dist/core/utils/network.mjs +27 -33
  88. package/dist/core/utils/number.mjs +7 -3
  89. package/dist/core/utils/package.mjs +20 -13
  90. package/dist/core/utils/paths.d.mts +8 -0
  91. package/dist/core/utils/paths.mjs +26 -7
  92. package/dist/core/utils/strings.mjs +19 -14
  93. package/dist/core/utils/syntax-errors.mjs +14 -16
  94. package/dist/core/utils/time.mjs +19 -15
  95. package/dist/core/utils/transform.mjs +129 -160
  96. package/dist/core/utils/types.d.mts +6 -0
  97. package/dist/core/utils/validation.mjs +43 -50
  98. package/dist/core/utils/virtual-modules.mjs +20 -12
  99. package/dist/core/utils/wsl.mjs +11 -3
  100. package/dist/core/wxt.mjs +65 -60
  101. package/dist/core/{zip.d.ts → zip.d.mts} +6 -2
  102. package/dist/core/zip.mjs +118 -140
  103. package/dist/index.d.mts +13 -0
  104. package/dist/index.mjs +13 -3
  105. package/dist/{modules.d.ts → modules.d.mts} +14 -16
  106. package/dist/modules.mjs +179 -51
  107. package/dist/testing/fake-browser.d.mts +2 -0
  108. package/dist/testing/fake-browser.mjs +3 -1
  109. package/dist/testing/index.d.mts +3 -0
  110. package/dist/testing/index.mjs +4 -2
  111. package/dist/testing/{wxt-vitest-plugin.d.ts → wxt-vitest-plugin.d.mts} +7 -9
  112. package/dist/testing/wxt-vitest-plugin.mjs +38 -19
  113. package/dist/types.d.mts +1475 -0
  114. package/dist/utils/app-config.d.mts +6 -0
  115. package/dist/utils/app-config.mjs +8 -2
  116. package/dist/utils/content-script-context.d.mts +134 -0
  117. package/dist/utils/content-script-context.mjs +187 -175
  118. package/dist/utils/content-script-ui/iframe.d.mts +42 -0
  119. package/dist/utils/content-script-ui/iframe.mjs +42 -27
  120. package/dist/utils/content-script-ui/integrated.d.mts +37 -0
  121. package/dist/utils/content-script-ui/integrated.mjs +36 -29
  122. package/dist/utils/content-script-ui/shadow-root.d.mts +80 -0
  123. package/dist/utils/content-script-ui/shadow-root.mjs +75 -82
  124. package/dist/utils/content-script-ui/shared.mjs +115 -150
  125. package/dist/utils/content-script-ui/types.d.mts +107 -0
  126. package/dist/utils/content-script-ui/types.mjs +1 -0
  127. package/dist/utils/{define-app-config.d.ts → define-app-config.d.mts} +5 -3
  128. package/dist/utils/define-app-config.mjs +22 -2
  129. package/dist/utils/define-background.d.mts +7 -0
  130. package/dist/utils/define-background.mjs +7 -3
  131. package/dist/utils/define-content-script.d.mts +6 -0
  132. package/dist/utils/define-content-script.mjs +6 -2
  133. package/dist/utils/define-unlisted-script.d.mts +7 -0
  134. package/dist/utils/define-unlisted-script.mjs +7 -3
  135. package/dist/utils/define-wxt-plugin.d.mts +6 -0
  136. package/dist/utils/define-wxt-plugin.mjs +6 -2
  137. package/dist/utils/inject-script.d.mts +41 -0
  138. package/dist/utils/inject-script.mjs +44 -34
  139. package/dist/utils/internal/custom-events.d.mts +9 -0
  140. package/dist/utils/internal/custom-events.mjs +18 -10
  141. package/dist/utils/internal/location-watcher.mjs +23 -20
  142. package/dist/utils/internal/logger.mjs +15 -12
  143. package/dist/utils/match-patterns.d.mts +1 -0
  144. package/dist/utils/match-patterns.mjs +3 -1
  145. package/dist/utils/{split-shadow-root-css.d.ts → split-shadow-root-css.d.mts} +6 -3
  146. package/dist/utils/split-shadow-root-css.mjs +16 -7
  147. package/dist/utils/storage.d.mts +1 -0
  148. package/dist/utils/storage.mjs +3 -1
  149. package/dist/version.d.mts +4 -0
  150. package/dist/version.mjs +5 -1
  151. package/dist/virtual/background-entrypoint.d.mts +4 -0
  152. package/dist/virtual/background-entrypoint.mjs +143 -161
  153. package/dist/virtual/content-script-isolated-world-entrypoint.d.mts +4 -0
  154. package/dist/virtual/content-script-isolated-world-entrypoint.mjs +26 -27
  155. package/dist/virtual/content-script-main-world-entrypoint.d.mts +4 -0
  156. package/dist/virtual/content-script-main-world-entrypoint.mjs +24 -24
  157. package/dist/virtual/mock-browser.d.mts +6 -0
  158. package/dist/virtual/mock-browser.mjs +5 -3
  159. package/dist/virtual/reload-html.d.mts +1 -0
  160. package/dist/virtual/reload-html.mjs +57 -53
  161. package/dist/virtual/unlisted-script-entrypoint.d.mts +4 -0
  162. package/dist/virtual/unlisted-script-entrypoint.mjs +35 -43
  163. package/package.json +56 -50
  164. package/dist/browser.d.ts +0 -30
  165. package/dist/builtin-modules/index.d.ts +0 -2
  166. package/dist/builtin-modules/unimport.d.ts +0 -5
  167. package/dist/cli/cli-utils.d.ts +0 -25
  168. package/dist/cli/commands.d.ts +0 -2
  169. package/dist/cli/index.d.ts +0 -1
  170. package/dist/core/builders/vite/index.d.ts +0 -7
  171. package/dist/core/builders/vite/plugins/bundleAnalysis.d.ts +0 -7
  172. package/dist/core/builders/vite/plugins/cssEntrypoints.d.ts +0 -13
  173. package/dist/core/builders/vite/plugins/defineImportMeta.d.ts +0 -14
  174. package/dist/core/builders/vite/plugins/devHtmlPrerender.d.ts +0 -7
  175. package/dist/core/builders/vite/plugins/devServerGlobals.d.ts +0 -6
  176. package/dist/core/builders/vite/plugins/download.d.ts +0 -10
  177. package/dist/core/builders/vite/plugins/entrypointGroupGlobals.d.ts +0 -6
  178. package/dist/core/builders/vite/plugins/extensionApiMock.d.ts +0 -6
  179. package/dist/core/builders/vite/plugins/globals.d.ts +0 -3
  180. package/dist/core/builders/vite/plugins/iifeFooter.d.ts +0 -8
  181. package/dist/core/builders/vite/plugins/index.d.ts +0 -16
  182. package/dist/core/builders/vite/plugins/noopBackground.d.ts +0 -6
  183. package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.d.ts +0 -6
  184. package/dist/core/builders/vite/plugins/resolveAppConfig.d.ts +0 -6
  185. package/dist/core/builders/vite/plugins/resolveVirtualModules.d.ts +0 -6
  186. package/dist/core/builders/vite/plugins/tsconfigPaths.d.ts +0 -3
  187. package/dist/core/builders/vite/plugins/wxtPluginLoader.d.ts +0 -6
  188. package/dist/core/define-config.d.ts +0 -2
  189. package/dist/core/define-web-ext-config.d.ts +0 -9
  190. package/dist/core/generate-wxt-dir.d.ts +0 -5
  191. package/dist/core/index.d.ts +0 -8
  192. package/dist/core/initialize.d.ts +0 -5
  193. package/dist/core/keyboard-shortcuts.d.ts +0 -12
  194. package/dist/core/package-managers/bun.d.ts +0 -2
  195. package/dist/core/package-managers/deno.d.ts +0 -2
  196. package/dist/core/package-managers/index.d.ts +0 -2
  197. package/dist/core/package-managers/npm.d.ts +0 -17
  198. package/dist/core/package-managers/pnpm.d.ts +0 -2
  199. package/dist/core/package-managers/types.d.ts +0 -2
  200. package/dist/core/package-managers/types.mjs +0 -0
  201. package/dist/core/package-managers/yarn.d.ts +0 -2
  202. package/dist/core/prepare.d.ts +0 -2
  203. package/dist/core/resolve-config.d.ts +0 -11
  204. package/dist/core/runners/index.d.ts +0 -2
  205. package/dist/core/runners/manual.d.ts +0 -5
  206. package/dist/core/runners/safari.d.ts +0 -5
  207. package/dist/core/runners/web-ext.d.ts +0 -5
  208. package/dist/core/runners/wsl.d.ts +0 -5
  209. package/dist/core/utils/arrays.d.ts +0 -13
  210. package/dist/core/utils/building/build-entrypoints.d.ts +0 -3
  211. package/dist/core/utils/building/detect-dev-changes.d.ts +0 -61
  212. package/dist/core/utils/building/find-entrypoints.d.ts +0 -5
  213. package/dist/core/utils/building/group-entrypoints.d.ts +0 -8
  214. package/dist/core/utils/building/index.d.ts +0 -6
  215. package/dist/core/utils/building/internal-build.d.ts +0 -12
  216. package/dist/core/utils/building/rebuild.d.ts +0 -23
  217. package/dist/core/utils/cache.d.ts +0 -8
  218. package/dist/core/utils/cli.d.ts +0 -3
  219. package/dist/core/utils/cli.mjs +0 -26
  220. package/dist/core/utils/constants.d.ts +0 -5
  221. package/dist/core/utils/content-scripts.d.ts +0 -12
  222. package/dist/core/utils/content-security-policy.d.ts +0 -14
  223. package/dist/core/utils/entrypoints.d.ts +0 -31
  224. package/dist/core/utils/env.d.ts +0 -5
  225. package/dist/core/utils/environments/browser-environment.d.ts +0 -3
  226. package/dist/core/utils/environments/environment.d.ts +0 -8
  227. package/dist/core/utils/environments/extension-environment.d.ts +0 -6
  228. package/dist/core/utils/environments/index.d.ts +0 -2
  229. package/dist/core/utils/eslint.d.ts +0 -1
  230. package/dist/core/utils/fs.d.ts +0 -13
  231. package/dist/core/utils/globals.d.ts +0 -11
  232. package/dist/core/utils/i18n.d.ts +0 -11
  233. package/dist/core/utils/log/index.d.ts +0 -4
  234. package/dist/core/utils/log/printBuildSummary.d.ts +0 -2
  235. package/dist/core/utils/log/printFileList.d.ts +0 -1
  236. package/dist/core/utils/log/printHeader.d.ts +0 -1
  237. package/dist/core/utils/log/printTable.d.ts +0 -1
  238. package/dist/core/utils/manifest.d.ts +0 -40
  239. package/dist/core/utils/minimatch-multiple.d.ts +0 -15
  240. package/dist/core/utils/network.d.ts +0 -7
  241. package/dist/core/utils/number.d.ts +0 -1
  242. package/dist/core/utils/package.d.ts +0 -6
  243. package/dist/core/utils/paths.d.ts +0 -11
  244. package/dist/core/utils/strings.d.ts +0 -14
  245. package/dist/core/utils/syntax-errors.d.ts +0 -11
  246. package/dist/core/utils/testing/fake-objects.d.ts +0 -11665
  247. package/dist/core/utils/testing/fake-objects.mjs +0 -326
  248. package/dist/core/utils/time.d.ts +0 -9
  249. package/dist/core/utils/transform.d.ts +0 -11
  250. package/dist/core/utils/types.d.ts +0 -13
  251. package/dist/core/utils/types.mjs +0 -0
  252. package/dist/core/utils/validation.d.ts +0 -15
  253. package/dist/core/utils/virtual-modules.d.ts +0 -22
  254. package/dist/core/utils/wsl.d.ts +0 -4
  255. package/dist/core/wxt.d.ts +0 -24
  256. package/dist/index.d.ts +0 -11
  257. package/dist/testing/fake-browser.d.ts +0 -10
  258. package/dist/testing/index.d.ts +0 -10
  259. package/dist/types.d.ts +0 -1459
  260. package/dist/types.mjs +0 -0
  261. package/dist/utils/app-config.d.ts +0 -2
  262. package/dist/utils/content-script-context.d.ts +0 -134
  263. package/dist/utils/content-script-ui/iframe.d.ts +0 -32
  264. package/dist/utils/content-script-ui/integrated.d.ts +0 -34
  265. package/dist/utils/content-script-ui/shadow-root.d.ts +0 -76
  266. package/dist/utils/content-script-ui/shared.d.ts +0 -5
  267. package/dist/utils/content-script-ui/types.d.ts +0 -104
  268. package/dist/utils/define-background.d.ts +0 -4
  269. package/dist/utils/define-content-script.d.ts +0 -3
  270. package/dist/utils/define-unlisted-script.d.ts +0 -4
  271. package/dist/utils/define-wxt-plugin.d.ts +0 -3
  272. package/dist/utils/inject-script.d.ts +0 -36
  273. package/dist/utils/internal/custom-events.d.ts +0 -10
  274. package/dist/utils/internal/dev-server-websocket.d.ts +0 -21
  275. package/dist/utils/internal/dev-server-websocket.mjs +0 -37
  276. package/dist/utils/internal/location-watcher.d.ts +0 -12
  277. package/dist/utils/internal/logger.d.ts +0 -9
  278. package/dist/utils/match-patterns.d.ts +0 -5
  279. package/dist/utils/storage.d.ts +0 -5
  280. package/dist/version.d.ts +0 -1
@@ -0,0 +1,6 @@
1
+ import { WxtAppConfig } from "./define-app-config.mjs";
2
+
3
+ //#region src/utils/app-config.d.ts
4
+ declare function useAppConfig(): WxtAppConfig;
5
+ //#endregion
6
+ export { useAppConfig };
@@ -1,4 +1,10 @@
1
1
  import appConfig from "virtual:app-config";
2
- export function useAppConfig() {
3
- return appConfig;
2
+
3
+ //#region src/utils/app-config.ts
4
+ /** @module wxt/utils/app-config */
5
+ function useAppConfig() {
6
+ return appConfig;
4
7
  }
8
+
9
+ //#endregion
10
+ export { useAppConfig };
@@ -0,0 +1,134 @@
1
+ import { WxtLocationChangeEvent } from "./internal/custom-events.mjs";
2
+ import { ContentScriptDefinition } from "../types.mjs";
3
+
4
+ //#region src/utils/content-script-context.d.ts
5
+ /**
6
+ * Implements [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
7
+ * Used to detect and stop content script code when the script is invalidated.
8
+ *
9
+ * It also provides several utilities like `ctx.setTimeout` and `ctx.setInterval` that should be used in
10
+ * content scripts instead of `window.setTimeout` or `window.setInterval`.
11
+ *
12
+ * To create context for testing, you can use the class's constructor:
13
+ *
14
+ * ```ts
15
+ * import { ContentScriptContext } from 'wxt/utils/content-scripts-context';
16
+ *
17
+ * test("storage listener should be removed when context is invalidated", () => {
18
+ * const ctx = new ContentScriptContext('test');
19
+ * const item = storage.defineItem("local:count", { defaultValue: 0 });
20
+ * const watcher = vi.fn();
21
+ *
22
+ * const unwatch = item.watch(watcher);
23
+ * ctx.onInvalidated(unwatch); // Listen for invalidate here
24
+ *
25
+ * await item.setValue(1);
26
+ * expect(watcher).toBeCalledTimes(1);
27
+ * expect(watcher).toBeCalledWith(1, 0);
28
+ *
29
+ * ctx.notifyInvalidated(); // Use this function to invalidate the context
30
+ * await item.setValue(2);
31
+ * expect(watcher).toBeCalledTimes(1);
32
+ * });
33
+ * ```
34
+ */
35
+ declare class ContentScriptContext implements AbortController {
36
+ private readonly contentScriptName;
37
+ readonly options?: Omit<ContentScriptDefinition, "main"> | undefined;
38
+ private static SCRIPT_STARTED_MESSAGE_TYPE;
39
+ private id;
40
+ private abortController;
41
+ private locationWatcher;
42
+ constructor(contentScriptName: string, options?: Omit<ContentScriptDefinition, "main"> | undefined);
43
+ get signal(): AbortSignal;
44
+ abort(reason?: any): void;
45
+ get isInvalid(): boolean;
46
+ get isValid(): boolean;
47
+ /**
48
+ * Add a listener that is called when the content script's context is invalidated.
49
+ *
50
+ * @returns A function to remove the listener.
51
+ *
52
+ * @example
53
+ * browser.runtime.onMessage.addListener(cb);
54
+ * const removeInvalidatedListener = ctx.onInvalidated(() => {
55
+ * browser.runtime.onMessage.removeListener(cb);
56
+ * })
57
+ * // ...
58
+ * removeInvalidatedListener();
59
+ */
60
+ onInvalidated(cb: () => void): () => void;
61
+ /**
62
+ * Return a promise that never resolves. Useful if you have an async function that shouldn't run
63
+ * after the context is expired.
64
+ *
65
+ * @example
66
+ * const getValueFromStorage = async () => {
67
+ * if (ctx.isInvalid) return ctx.block();
68
+ *
69
+ * // ...
70
+ * }
71
+ */
72
+ block<T>(): Promise<T>;
73
+ /**
74
+ * Wrapper around `window.setInterval` that automatically clears the interval when invalidated.
75
+ *
76
+ * Intervals can be cleared by calling the normal `clearInterval` function.
77
+ */
78
+ setInterval(handler: () => void, timeout?: number): number;
79
+ /**
80
+ * Wrapper around `window.setTimeout` that automatically clears the interval when invalidated.
81
+ *
82
+ * Timeouts can be cleared by calling the normal `setTimeout` function.
83
+ */
84
+ setTimeout(handler: () => void, timeout?: number): number;
85
+ /**
86
+ * Wrapper around `window.requestAnimationFrame` that automatically cancels the request when
87
+ * invalidated.
88
+ *
89
+ * Callbacks can be canceled by calling the normal `cancelAnimationFrame` function.
90
+ */
91
+ requestAnimationFrame(callback: FrameRequestCallback): number;
92
+ /**
93
+ * Wrapper around `window.requestIdleCallback` that automatically cancels the request when
94
+ * invalidated.
95
+ *
96
+ * Callbacks can be canceled by calling the normal `cancelIdleCallback` function.
97
+ */
98
+ requestIdleCallback(callback: IdleRequestCallback, options?: IdleRequestOptions): number;
99
+ /**
100
+ * Call `target.addEventListener` and remove the event listener when the context is invalidated.
101
+ *
102
+ * Listeners can be canceled by calling the normal `removeEventListener` function.
103
+ *
104
+ * Includes additional events useful for content scripts:
105
+ *
106
+ * - `"wxt:locationchange"` - Triggered when HTML5 history mode is used to change URL. Content
107
+ * scripts are not reloaded when navigating this way, so this can be used to reset the content
108
+ * script state on URL change, or run custom code.
109
+ *
110
+ * @example
111
+ * ctx.addEventListener(document, "visibilitychange", () => {
112
+ * // ...
113
+ * });
114
+ * ctx.addEventListener(window, "wxt:locationchange", () => {
115
+ * // ...
116
+ * });
117
+ */
118
+ addEventListener<TType extends keyof WxtWindowEventMap>(target: Window, type: TType, handler: (event: WxtWindowEventMap[TType]) => void, options?: AddEventListenerOptions): void;
119
+ addEventListener<TType extends keyof DocumentEventMap>(target: Document, type: TType, handler: (event: DocumentEventMap[TType]) => void, options?: AddEventListenerOptions): void;
120
+ addEventListener<TTarget extends EventTarget>(target: TTarget, ...params: Parameters<TTarget['addEventListener']>): void;
121
+ /**
122
+ * @internal
123
+ * Abort the abort controller and execute all `onInvalidated` listeners.
124
+ */
125
+ notifyInvalidated(): void;
126
+ stopOldScripts(): void;
127
+ verifyScriptStartedEvent(event: CustomEvent): boolean;
128
+ listenForNewerScripts(): void;
129
+ }
130
+ interface WxtWindowEventMap extends WindowEventMap {
131
+ 'wxt:locationchange': WxtLocationChangeEvent;
132
+ }
133
+ //#endregion
134
+ export { ContentScriptContext, WxtWindowEventMap };
@@ -1,176 +1,188 @@
1
- import { browser } from "wxt/browser";
2
- import { logger } from "../utils/internal/logger.mjs";
3
- import {
4
- getUniqueEventName
5
- } from "./internal/custom-events.mjs";
1
+ import { logger } from "./internal/logger.mjs";
2
+ import { getUniqueEventName } from "./internal/custom-events.mjs";
6
3
  import { createLocationWatcher } from "./internal/location-watcher.mjs";
7
- export class ContentScriptContext {
8
- constructor(contentScriptName, options) {
9
- this.contentScriptName = contentScriptName;
10
- this.options = options;
11
- this.abortController = new AbortController();
12
- if (this.isTopFrame) {
13
- this.listenForNewerScripts({ ignoreFirstEvent: true });
14
- this.stopOldScripts();
15
- } else {
16
- this.listenForNewerScripts();
17
- }
18
- }
19
- static SCRIPT_STARTED_MESSAGE_TYPE = getUniqueEventName(
20
- "wxt:content-script-started"
21
- );
22
- isTopFrame = window.self === window.top;
23
- abortController;
24
- locationWatcher = createLocationWatcher(this);
25
- receivedMessageIds = /* @__PURE__ */ new Set();
26
- get signal() {
27
- return this.abortController.signal;
28
- }
29
- abort(reason) {
30
- return this.abortController.abort(reason);
31
- }
32
- get isInvalid() {
33
- if (browser.runtime.id == null) {
34
- this.notifyInvalidated();
35
- }
36
- return this.signal.aborted;
37
- }
38
- get isValid() {
39
- return !this.isInvalid;
40
- }
41
- /**
42
- * Add a listener that is called when the content script's context is invalidated.
43
- *
44
- * @returns A function to remove the listener.
45
- *
46
- * @example
47
- * browser.runtime.onMessage.addListener(cb);
48
- * const removeInvalidatedListener = ctx.onInvalidated(() => {
49
- * browser.runtime.onMessage.removeListener(cb);
50
- * })
51
- * // ...
52
- * removeInvalidatedListener();
53
- */
54
- onInvalidated(cb) {
55
- this.signal.addEventListener("abort", cb);
56
- return () => this.signal.removeEventListener("abort", cb);
57
- }
58
- /**
59
- * Return a promise that never resolves. Useful if you have an async function that shouldn't run
60
- * after the context is expired.
61
- *
62
- * @example
63
- * const getValueFromStorage = async () => {
64
- * if (ctx.isInvalid) return ctx.block();
65
- *
66
- * // ...
67
- * }
68
- */
69
- block() {
70
- return new Promise(() => {
71
- });
72
- }
73
- /**
74
- * Wrapper around `window.setInterval` that automatically clears the interval when invalidated.
75
- *
76
- * Intervals can be cleared by calling the normal `clearInterval` function.
77
- */
78
- setInterval(handler, timeout) {
79
- const id = setInterval(() => {
80
- if (this.isValid) handler();
81
- }, timeout);
82
- this.onInvalidated(() => clearInterval(id));
83
- return id;
84
- }
85
- /**
86
- * Wrapper around `window.setTimeout` that automatically clears the interval when invalidated.
87
- *
88
- * Timeouts can be cleared by calling the normal `setTimeout` function.
89
- */
90
- setTimeout(handler, timeout) {
91
- const id = setTimeout(() => {
92
- if (this.isValid) handler();
93
- }, timeout);
94
- this.onInvalidated(() => clearTimeout(id));
95
- return id;
96
- }
97
- /**
98
- * Wrapper around `window.requestAnimationFrame` that automatically cancels the request when
99
- * invalidated.
100
- *
101
- * Callbacks can be canceled by calling the normal `cancelAnimationFrame` function.
102
- */
103
- requestAnimationFrame(callback) {
104
- const id = requestAnimationFrame((...args) => {
105
- if (this.isValid) callback(...args);
106
- });
107
- this.onInvalidated(() => cancelAnimationFrame(id));
108
- return id;
109
- }
110
- /**
111
- * Wrapper around `window.requestIdleCallback` that automatically cancels the request when
112
- * invalidated.
113
- *
114
- * Callbacks can be canceled by calling the normal `cancelIdleCallback` function.
115
- */
116
- requestIdleCallback(callback, options) {
117
- const id = requestIdleCallback((...args) => {
118
- if (!this.signal.aborted) callback(...args);
119
- }, options);
120
- this.onInvalidated(() => cancelIdleCallback(id));
121
- return id;
122
- }
123
- addEventListener(target, type, handler, options) {
124
- if (type === "wxt:locationchange") {
125
- if (this.isValid) this.locationWatcher.run();
126
- }
127
- target.addEventListener?.(
128
- type.startsWith("wxt:") ? getUniqueEventName(type) : type,
129
- handler,
130
- {
131
- ...options,
132
- signal: this.signal
133
- }
134
- );
135
- }
136
- /**
137
- * @internal
138
- * Abort the abort controller and execute all `onInvalidated` listeners.
139
- */
140
- notifyInvalidated() {
141
- this.abort("Content script context invalidated");
142
- logger.debug(
143
- `Content script "${this.contentScriptName}" context invalidated`
144
- );
145
- }
146
- stopOldScripts() {
147
- window.postMessage(
148
- {
149
- type: ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE,
150
- contentScriptName: this.contentScriptName,
151
- messageId: Math.random().toString(36).slice(2)
152
- },
153
- "*"
154
- );
155
- }
156
- verifyScriptStartedEvent(event) {
157
- const isScriptStartedEvent = event.data?.type === ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE;
158
- const isSameContentScript = event.data?.contentScriptName === this.contentScriptName;
159
- const isNotDuplicate = !this.receivedMessageIds.has(event.data?.messageId);
160
- return isScriptStartedEvent && isSameContentScript && isNotDuplicate;
161
- }
162
- listenForNewerScripts(options) {
163
- let isFirst = true;
164
- const cb = (event) => {
165
- if (this.verifyScriptStartedEvent(event)) {
166
- this.receivedMessageIds.add(event.data.messageId);
167
- const wasFirst = isFirst;
168
- isFirst = false;
169
- if (wasFirst && options?.ignoreFirstEvent) return;
170
- this.notifyInvalidated();
171
- }
172
- };
173
- addEventListener("message", cb);
174
- this.onInvalidated(() => removeEventListener("message", cb));
175
- }
176
- }
4
+ import { browser } from "wxt/browser";
5
+
6
+ //#region src/utils/content-script-context.ts
7
+ /**
8
+ * Implements [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
9
+ * Used to detect and stop content script code when the script is invalidated.
10
+ *
11
+ * It also provides several utilities like `ctx.setTimeout` and `ctx.setInterval` that should be used in
12
+ * content scripts instead of `window.setTimeout` or `window.setInterval`.
13
+ *
14
+ * To create context for testing, you can use the class's constructor:
15
+ *
16
+ * ```ts
17
+ * import { ContentScriptContext } from 'wxt/utils/content-scripts-context';
18
+ *
19
+ * test("storage listener should be removed when context is invalidated", () => {
20
+ * const ctx = new ContentScriptContext('test');
21
+ * const item = storage.defineItem("local:count", { defaultValue: 0 });
22
+ * const watcher = vi.fn();
23
+ *
24
+ * const unwatch = item.watch(watcher);
25
+ * ctx.onInvalidated(unwatch); // Listen for invalidate here
26
+ *
27
+ * await item.setValue(1);
28
+ * expect(watcher).toBeCalledTimes(1);
29
+ * expect(watcher).toBeCalledWith(1, 0);
30
+ *
31
+ * ctx.notifyInvalidated(); // Use this function to invalidate the context
32
+ * await item.setValue(2);
33
+ * expect(watcher).toBeCalledTimes(1);
34
+ * });
35
+ * ```
36
+ */
37
+ var ContentScriptContext = class ContentScriptContext {
38
+ static SCRIPT_STARTED_MESSAGE_TYPE = getUniqueEventName("wxt:content-script-started");
39
+ id;
40
+ abortController;
41
+ locationWatcher = createLocationWatcher(this);
42
+ constructor(contentScriptName, options) {
43
+ this.contentScriptName = contentScriptName;
44
+ this.options = options;
45
+ this.id = Math.random().toString(36).slice(2);
46
+ this.abortController = new AbortController();
47
+ this.stopOldScripts();
48
+ this.listenForNewerScripts();
49
+ }
50
+ get signal() {
51
+ return this.abortController.signal;
52
+ }
53
+ abort(reason) {
54
+ return this.abortController.abort(reason);
55
+ }
56
+ get isInvalid() {
57
+ if (browser.runtime?.id == null) this.notifyInvalidated();
58
+ return this.signal.aborted;
59
+ }
60
+ get isValid() {
61
+ return !this.isInvalid;
62
+ }
63
+ /**
64
+ * Add a listener that is called when the content script's context is invalidated.
65
+ *
66
+ * @returns A function to remove the listener.
67
+ *
68
+ * @example
69
+ * browser.runtime.onMessage.addListener(cb);
70
+ * const removeInvalidatedListener = ctx.onInvalidated(() => {
71
+ * browser.runtime.onMessage.removeListener(cb);
72
+ * })
73
+ * // ...
74
+ * removeInvalidatedListener();
75
+ */
76
+ onInvalidated(cb) {
77
+ this.signal.addEventListener("abort", cb);
78
+ return () => this.signal.removeEventListener("abort", cb);
79
+ }
80
+ /**
81
+ * Return a promise that never resolves. Useful if you have an async function that shouldn't run
82
+ * after the context is expired.
83
+ *
84
+ * @example
85
+ * const getValueFromStorage = async () => {
86
+ * if (ctx.isInvalid) return ctx.block();
87
+ *
88
+ * // ...
89
+ * }
90
+ */
91
+ block() {
92
+ return new Promise(() => {});
93
+ }
94
+ /**
95
+ * Wrapper around `window.setInterval` that automatically clears the interval when invalidated.
96
+ *
97
+ * Intervals can be cleared by calling the normal `clearInterval` function.
98
+ */
99
+ setInterval(handler, timeout) {
100
+ const id = setInterval(() => {
101
+ if (this.isValid) handler();
102
+ }, timeout);
103
+ this.onInvalidated(() => clearInterval(id));
104
+ return id;
105
+ }
106
+ /**
107
+ * Wrapper around `window.setTimeout` that automatically clears the interval when invalidated.
108
+ *
109
+ * Timeouts can be cleared by calling the normal `setTimeout` function.
110
+ */
111
+ setTimeout(handler, timeout) {
112
+ const id = setTimeout(() => {
113
+ if (this.isValid) handler();
114
+ }, timeout);
115
+ this.onInvalidated(() => clearTimeout(id));
116
+ return id;
117
+ }
118
+ /**
119
+ * Wrapper around `window.requestAnimationFrame` that automatically cancels the request when
120
+ * invalidated.
121
+ *
122
+ * Callbacks can be canceled by calling the normal `cancelAnimationFrame` function.
123
+ */
124
+ requestAnimationFrame(callback) {
125
+ const id = requestAnimationFrame((...args) => {
126
+ if (this.isValid) callback(...args);
127
+ });
128
+ this.onInvalidated(() => cancelAnimationFrame(id));
129
+ return id;
130
+ }
131
+ /**
132
+ * Wrapper around `window.requestIdleCallback` that automatically cancels the request when
133
+ * invalidated.
134
+ *
135
+ * Callbacks can be canceled by calling the normal `cancelIdleCallback` function.
136
+ */
137
+ requestIdleCallback(callback, options) {
138
+ const id = requestIdleCallback((...args) => {
139
+ if (!this.signal.aborted) callback(...args);
140
+ }, options);
141
+ this.onInvalidated(() => cancelIdleCallback(id));
142
+ return id;
143
+ }
144
+ addEventListener(target, type, handler, options) {
145
+ if (type === "wxt:locationchange") {
146
+ if (this.isValid) this.locationWatcher.run();
147
+ }
148
+ target.addEventListener?.(type.startsWith("wxt:") ? getUniqueEventName(type) : type, handler, {
149
+ ...options,
150
+ signal: this.signal
151
+ });
152
+ }
153
+ /**
154
+ * @internal
155
+ * Abort the abort controller and execute all `onInvalidated` listeners.
156
+ */
157
+ notifyInvalidated() {
158
+ this.abort("Content script context invalidated");
159
+ logger.debug(`Content script "${this.contentScriptName}" context invalidated`);
160
+ }
161
+ stopOldScripts() {
162
+ document.dispatchEvent(new CustomEvent(ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE, { detail: {
163
+ contentScriptName: this.contentScriptName,
164
+ messageId: this.id
165
+ } }));
166
+ window.postMessage({
167
+ type: ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE,
168
+ contentScriptName: this.contentScriptName,
169
+ messageId: this.id
170
+ }, "*");
171
+ }
172
+ verifyScriptStartedEvent(event) {
173
+ const isSameContentScript = event.detail?.contentScriptName === this.contentScriptName;
174
+ const isFromSelf = event.detail?.messageId === this.id;
175
+ return isSameContentScript && !isFromSelf;
176
+ }
177
+ listenForNewerScripts() {
178
+ const cb = (event) => {
179
+ if (!(event instanceof CustomEvent) || !this.verifyScriptStartedEvent(event)) return;
180
+ this.notifyInvalidated();
181
+ };
182
+ document.addEventListener(ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE, cb);
183
+ this.onInvalidated(() => document.removeEventListener(ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE, cb));
184
+ }
185
+ };
186
+
187
+ //#endregion
188
+ export { ContentScriptContext };
@@ -0,0 +1,42 @@
1
+ import { ContentScriptContext } from "../content-script-context.mjs";
2
+ import { ContentScriptUi, ContentScriptUiOptions } from "./types.mjs";
3
+ import * as wxt_browser0 from "wxt/browser";
4
+
5
+ //#region src/utils/content-script-ui/iframe.d.ts
6
+ /**
7
+ * Create a content script UI using an iframe.
8
+ *
9
+ * @see https://wxt.dev/guide/essentials/content-scripts.html#iframe
10
+ */
11
+ declare function createIframeUi<TMounted>(ctx: ContentScriptContext, options: IframeContentScriptUiOptions<TMounted>): IframeContentScriptUi<TMounted>;
12
+ interface IframeContentScriptUi<TMounted> extends ContentScriptUi<TMounted> {
13
+ /**
14
+ * The iframe added to the DOM.
15
+ */
16
+ iframe: HTMLIFrameElement;
17
+ /**
18
+ * A wrapper div that assists in positioning.
19
+ */
20
+ wrapper: HTMLDivElement;
21
+ }
22
+ type IframeContentScriptUiOptions<TMounted> = ContentScriptUiOptions<TMounted> & {
23
+ /**
24
+ * The path to the HTML page that will be shown in the iframe. This string is passed into
25
+ * `browser.runtime.getURL`.
26
+ */
27
+ page: wxt_browser0.HtmlPublicPath;
28
+ /**
29
+ * Callback executed when mounting the UI. Use this function to customize the iframe or wrapper
30
+ * element's appearance. It is called every time `ui.mount()` is called.
31
+ *
32
+ * Optionally return a value that can be accessed at `ui.mounted` or in the `onRemove` callback.
33
+ */
34
+ onMount?: (wrapper: HTMLElement, iframe: HTMLIFrameElement) => TMounted;
35
+ /**
36
+ * Callback executed before mounting the UI. Use this function to customize the iframe or wrapper
37
+ * elements before they are injected into the DOM. It is called every time `ui.mount()` is called.
38
+ */
39
+ onBeforeMount?: (wrapper: HTMLElement, iframe: HTMLIFrameElement) => void;
40
+ };
41
+ //#endregion
42
+ export { IframeContentScriptUi, IframeContentScriptUiOptions, createIframeUi };
@@ -1,29 +1,44 @@
1
- import { browser } from "wxt/browser";
2
1
  import { applyPosition, createMountFunctions, mountUi } from "./shared.mjs";
3
- export function createIframeUi(ctx, options) {
4
- const wrapper = document.createElement("div");
5
- const iframe = document.createElement("iframe");
6
- iframe.src = browser.runtime.getURL(options.page);
7
- wrapper.appendChild(iframe);
8
- let mounted = void 0;
9
- const mount = () => {
10
- applyPosition(wrapper, iframe, options);
11
- mountUi(wrapper, options);
12
- mounted = options.onMount?.(wrapper, iframe);
13
- };
14
- const remove = () => {
15
- options.onRemove?.(mounted);
16
- wrapper.remove();
17
- mounted = void 0;
18
- };
19
- const mountFunctions = createMountFunctions({ mount, remove }, options);
20
- ctx.onInvalidated(remove);
21
- return {
22
- get mounted() {
23
- return mounted;
24
- },
25
- iframe,
26
- wrapper,
27
- ...mountFunctions
28
- };
2
+ import { browser } from "wxt/browser";
3
+
4
+ //#region src/utils/content-script-ui/iframe.ts
5
+ /** @module wxt/utils/content-script-ui/iframe */
6
+ /**
7
+ * Create a content script UI using an iframe.
8
+ *
9
+ * @see https://wxt.dev/guide/essentials/content-scripts.html#iframe
10
+ */
11
+ function createIframeUi(ctx, options) {
12
+ const wrapper = document.createElement("div");
13
+ const iframe = document.createElement("iframe");
14
+ iframe.src = browser.runtime.getURL(options.page);
15
+ wrapper.appendChild(iframe);
16
+ let mounted;
17
+ const mount = () => {
18
+ applyPosition(wrapper, iframe, options);
19
+ options.onBeforeMount?.(wrapper, iframe);
20
+ mountUi(wrapper, options);
21
+ mounted = options.onMount?.(wrapper, iframe);
22
+ };
23
+ const remove = () => {
24
+ options.onRemove?.(mounted);
25
+ wrapper.remove();
26
+ mounted = void 0;
27
+ };
28
+ const mountFunctions = createMountFunctions({
29
+ mount,
30
+ remove
31
+ }, options);
32
+ ctx.onInvalidated(remove);
33
+ return {
34
+ get mounted() {
35
+ return mounted;
36
+ },
37
+ iframe,
38
+ wrapper,
39
+ ...mountFunctions
40
+ };
29
41
  }
42
+
43
+ //#endregion
44
+ export { createIframeUi };