wxt 0.5.5 → 0.5.6
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.
- package/dist/cli.cjs +20 -4
- package/dist/client.d.ts +53 -1
- package/dist/index.cjs +19 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -2
- package/dist/index.d.ts +54 -2
- package/dist/index.js +19 -3
- package/dist/index.js.map +1 -1
- package/dist/virtual-modules/content-script-entrypoint.js +118 -1
- package/dist/virtual-modules/content-script-entrypoint.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,10 +17,127 @@ var logger = {
|
|
|
17
17
|
error: (...args) => print(console.error, ...args)
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
// src/client/browser.ts
|
|
21
|
+
import originalBrowser from "webextension-polyfill";
|
|
22
|
+
var browser = originalBrowser;
|
|
23
|
+
|
|
24
|
+
// src/client/utils/ContentScriptContext.ts
|
|
25
|
+
var ContentScriptContext = class _ContentScriptContext extends AbortController {
|
|
26
|
+
constructor(contentScriptName) {
|
|
27
|
+
super();
|
|
28
|
+
this.contentScriptName = contentScriptName;
|
|
29
|
+
if (this.#isTopFrame) {
|
|
30
|
+
this.#stopOldScripts();
|
|
31
|
+
}
|
|
32
|
+
this.setTimeout(() => {
|
|
33
|
+
this.#listenForNewerScripts();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
static SCRIPT_STARTED_MESSAGE_TYPE = "wxt:content-script-started";
|
|
37
|
+
#isTopFrame = window.self === window.top;
|
|
38
|
+
get isInvalid() {
|
|
39
|
+
if (browser.runtime.id == null) {
|
|
40
|
+
this.notifyInvalidated();
|
|
41
|
+
}
|
|
42
|
+
return this.signal.aborted;
|
|
43
|
+
}
|
|
44
|
+
get isValid() {
|
|
45
|
+
return !this.isInvalid;
|
|
46
|
+
}
|
|
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) {
|
|
61
|
+
this.signal.addEventListener("abort", cb);
|
|
62
|
+
return () => this.signal.removeEventListener("abort", cb);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wrapper around `window.setInterval` that automatically clears the interval when invalidated.
|
|
66
|
+
*/
|
|
67
|
+
setInterval(handler, timeout) {
|
|
68
|
+
const id = setInterval(() => {
|
|
69
|
+
if (this.isValid)
|
|
70
|
+
handler();
|
|
71
|
+
}, timeout);
|
|
72
|
+
this.onInvalidated(() => clearInterval(id));
|
|
73
|
+
return id;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Wrapper around `window.setTimeout` that automatically clears the interval when invalidated.
|
|
77
|
+
*/
|
|
78
|
+
setTimeout(handler, timeout) {
|
|
79
|
+
const id = setTimeout(() => {
|
|
80
|
+
if (this.isValid)
|
|
81
|
+
handler();
|
|
82
|
+
}, timeout);
|
|
83
|
+
this.onInvalidated(() => clearTimeout(id));
|
|
84
|
+
return id;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Wrapper around `window.requestAnimationFrame` that automatically cancels the request when
|
|
88
|
+
* invalidated.
|
|
89
|
+
*/
|
|
90
|
+
requestAnimationFrame(callback) {
|
|
91
|
+
const id = requestAnimationFrame((...args) => {
|
|
92
|
+
if (this.isValid)
|
|
93
|
+
callback(...args);
|
|
94
|
+
});
|
|
95
|
+
this.onInvalidated(() => cancelAnimationFrame(id));
|
|
96
|
+
return id;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Wrapper around `window.requestIdleCallback` that automatically cancels the request when
|
|
100
|
+
* invalidated.
|
|
101
|
+
*/
|
|
102
|
+
requestIdleCallback(callback, options) {
|
|
103
|
+
const id = requestIdleCallback((...args) => {
|
|
104
|
+
if (!this.signal.aborted)
|
|
105
|
+
callback(...args);
|
|
106
|
+
}, options);
|
|
107
|
+
this.onInvalidated(() => cancelIdleCallback(id));
|
|
108
|
+
return id;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Abort the abort controller and execute all `onInvalidated` listeners.
|
|
112
|
+
*/
|
|
113
|
+
notifyInvalidated() {
|
|
114
|
+
this.abort("Content script context invalidated");
|
|
115
|
+
logger.debug(
|
|
116
|
+
`Content script "${this.contentScriptName}" context invalidated`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
#stopOldScripts() {
|
|
120
|
+
window.postMessage({
|
|
121
|
+
event: _ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE,
|
|
122
|
+
contentScriptName: this.contentScriptName
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
#listenForNewerScripts() {
|
|
126
|
+
const cb = (event) => {
|
|
127
|
+
if (event.data?.type === _ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE && event.data?.contentScriptName === this.contentScriptName) {
|
|
128
|
+
this.notifyInvalidated();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
addEventListener("message", cb);
|
|
132
|
+
this.onInvalidated(() => removeEventListener("message", cb));
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
20
136
|
// src/client/virtual-modules/content-script-entrypoint.ts
|
|
21
137
|
(async () => {
|
|
22
138
|
try {
|
|
23
|
-
|
|
139
|
+
const ctx = new ContentScriptContext(__ENTRYPOINT__);
|
|
140
|
+
await definition.main(ctx);
|
|
24
141
|
} catch (err) {
|
|
25
142
|
logger.error("The content script crashed on startup!", err);
|
|
26
143
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/virtual-modules/content-script-entrypoint.ts","../../src/client/utils/logger.ts"],"sourcesContent":["import definition from 'virtual:user-content-script';\nimport { logger } from '../utils/logger';\n\n(async () => {\n try {\n await definition.main();\n } catch (err) {\n logger.error('The content script crashed on startup!', err);\n }\n})();\n","function print(method: (...args: any[]) => void, ...args: any[]) {\n if (typeof args[0] === 'string') {\n const message = args.shift();\n method(`[wxt] ${message}`, ...args);\n } else {\n method('[wxt]', ...args);\n }\n}\n\n/**\n * Wrapper around `console` with a \"[wxt]\" prefix\n */\nexport const logger = {\n debug: (...args: any[]) => print(console.debug, ...args),\n log: (...args: any[]) => print(console.log, ...args),\n warn: (...args: any[]) => print(console.warn, ...args),\n error: (...args: any[]) => print(console.error, ...args),\n};\n"],"mappings":";AAAA,OAAO,gBAAgB;;;ACAvB,SAAS,MAAM,WAAqC,MAAa;AAC/D,MAAI,OAAO,KAAK,CAAC,MAAM,UAAU;AAC/B,UAAM,UAAU,KAAK,MAAM;AAC3B,WAAO,SAAS,OAAO,IAAI,GAAG,IAAI;AAAA,EACpC,OAAO;AACL,WAAO,SAAS,GAAG,IAAI;AAAA,EACzB;AACF;AAKO,IAAM,SAAS;AAAA,EACpB,OAAO,IAAI,SAAgB,MAAM,QAAQ,OAAO,GAAG,IAAI;AAAA,EACvD,KAAK,IAAI,SAAgB,MAAM,QAAQ,KAAK,GAAG,IAAI;AAAA,EACnD,MAAM,IAAI,SAAgB,MAAM,QAAQ,MAAM,GAAG,IAAI;AAAA,EACrD,OAAO,IAAI,SAAgB,MAAM,QAAQ,OAAO,GAAG,IAAI;AACzD;;;
|
|
1
|
+
{"version":3,"sources":["../../src/client/virtual-modules/content-script-entrypoint.ts","../../src/client/utils/logger.ts","../../src/client/browser.ts","../../src/client/utils/ContentScriptContext.ts"],"sourcesContent":["import definition from 'virtual:user-content-script';\nimport { logger } from '../utils/logger';\nimport { ContentScriptContext } from '../utils/ContentScriptContext';\n\n(async () => {\n try {\n const ctx = new ContentScriptContext(__ENTRYPOINT__);\n\n await definition.main(ctx);\n } catch (err) {\n logger.error('The content script crashed on startup!', err);\n }\n})();\n","function print(method: (...args: any[]) => void, ...args: any[]) {\n if (typeof args[0] === 'string') {\n const message = args.shift();\n method(`[wxt] ${message}`, ...args);\n } else {\n method('[wxt]', ...args);\n }\n}\n\n/**\n * Wrapper around `console` with a \"[wxt]\" prefix\n */\nexport const logger = {\n debug: (...args: any[]) => print(console.debug, ...args),\n log: (...args: any[]) => print(console.log, ...args),\n warn: (...args: any[]) => print(console.warn, ...args),\n error: (...args: any[]) => print(console.error, ...args),\n};\n","import originalBrowser, { Browser, Runtime, I18n } from 'webextension-polyfill';\n\nexport interface AugmentedBrowser extends Browser {\n runtime: WxtRuntime;\n i18n: WxtI18n;\n}\n\nexport interface WxtRuntime extends Runtime.Static {\n // Overriden per-project\n}\n\nexport interface WxtI18n extends I18n.Static {\n // Overriden per-project\n}\n\nexport const browser: AugmentedBrowser = originalBrowser;\n","import { browser } from '../browser';\nimport { logger } from './logger';\n\n/**\n * Extends [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).\n * Used to detect and stop content script code when the script is invalidated.\n *\n * It also provides several utilities like `ctx.setTimeout` and `ctx.setInterval` that should be used in\n * content scripts instead of `window.setTimeout` or `window.setInterval`.\n */\nexport class ContentScriptContext extends AbortController {\n static SCRIPT_STARTED_MESSAGE_TYPE = 'wxt:content-script-started';\n\n #isTopFrame = window.self === window.top;\n\n constructor(private readonly contentScriptName: string) {\n super();\n\n if (this.#isTopFrame) {\n this.#stopOldScripts();\n }\n this.setTimeout(() => {\n // Run on next tick so the listener it adds isn't triggered by stopOldScript\n this.#listenForNewerScripts();\n });\n }\n\n get isInvalid(): boolean {\n if (browser.runtime.id == null) {\n this.notifyInvalidated(); // Sets `signal.aborted` to true\n }\n return this.signal.aborted;\n }\n\n get isValid(): boolean {\n return !this.isInvalid;\n }\n\n /**\n * Add a listener that is called when the content script's context is invalidated.\n *\n * @returns A function to remove the listener.\n *\n * @example\n * browser.runtime.onMessage.addListener(cb);\n * const removeInvalidatedListener = ctx.onInvalidated(() => {\n * browser.runtime.onMessage.removeListener(cb);\n * })\n * // ...\n * removeInvalidatedListener();\n */\n onInvalidated(cb: () => void): () => void {\n this.signal.addEventListener('abort', cb);\n return () => this.signal.removeEventListener('abort', cb);\n }\n\n /**\n * Wrapper around `window.setInterval` that automatically clears the interval when invalidated.\n */\n setInterval(handler: () => void, timeout?: number): number {\n const id = setInterval(() => {\n if (this.isValid) handler();\n }, timeout) as unknown as number;\n this.onInvalidated(() => clearInterval(id));\n return id;\n }\n\n /**\n * Wrapper around `window.setTimeout` that automatically clears the interval when invalidated.\n */\n setTimeout(handler: () => void, timeout?: number): number {\n const id = setTimeout(() => {\n if (this.isValid) handler();\n }, timeout) as unknown as number;\n this.onInvalidated(() => clearTimeout(id));\n return id;\n }\n\n /**\n * Wrapper around `window.requestAnimationFrame` that automatically cancels the request when\n * invalidated.\n */\n requestAnimationFrame(callback: FrameRequestCallback): number {\n const id = requestAnimationFrame((...args) => {\n if (this.isValid) callback(...args);\n });\n\n this.onInvalidated(() => cancelAnimationFrame(id));\n return id;\n }\n\n /**\n * Wrapper around `window.requestIdleCallback` that automatically cancels the request when\n * invalidated.\n */\n requestIdleCallback(\n callback: IdleRequestCallback,\n options?: IdleRequestOptions,\n ): number {\n const id = requestIdleCallback((...args) => {\n if (!this.signal.aborted) callback(...args);\n }, options);\n\n this.onInvalidated(() => cancelIdleCallback(id));\n return id;\n }\n\n /**\n * Abort the abort controller and execute all `onInvalidated` listeners.\n */\n notifyInvalidated() {\n this.abort('Content script context invalidated');\n logger.debug(\n `Content script \"${this.contentScriptName}\" context invalidated`,\n );\n }\n\n #stopOldScripts() {\n // Use postMessage so it get's sent to all the frames of the page.\n window.postMessage({\n event: ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE,\n contentScriptName: this.contentScriptName,\n });\n }\n\n #listenForNewerScripts() {\n const cb = (event: MessageEvent) => {\n if (\n event.data?.type === ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE &&\n event.data?.contentScriptName === this.contentScriptName\n ) {\n this.notifyInvalidated();\n }\n };\n\n addEventListener('message', cb);\n this.onInvalidated(() => removeEventListener('message', cb));\n }\n}\n"],"mappings":"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","names":[]}
|