Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3d409f250 | |||
| b6758ca9fa | |||
| 2672308946 |
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## v0.8.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.1...v0.8.2)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- **firefox:** Stop extending `AbortController` to fix crash in content scripts ([#176](https://github.com/wxt-dev/wxt/pull/176))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Improve output consistency ([#175](https://github.com/wxt-dev/wxt/pull/175))
|
||||
|
||||
## v0.8.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.0...v0.8.1)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wxt",
|
||||
"type": "module",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"description": "Next gen framework for developing web extensions",
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
|
||||
@@ -3,23 +3,23 @@ import { browser } from '../browser';
|
||||
import { logger } from './logger';
|
||||
|
||||
/**
|
||||
* Extends [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
|
||||
* Implements [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
|
||||
* Used to detect and stop content script code when the script is invalidated.
|
||||
*
|
||||
* It also provides several utilities like `ctx.setTimeout` and `ctx.setInterval` that should be used in
|
||||
* content scripts instead of `window.setTimeout` or `window.setInterval`.
|
||||
*/
|
||||
export class ContentScriptContext extends AbortController {
|
||||
export class ContentScriptContext implements AbortController {
|
||||
private static SCRIPT_STARTED_MESSAGE_TYPE = 'wxt:content-script-started';
|
||||
|
||||
#isTopFrame = window.self === window.top;
|
||||
#abortController: AbortController;
|
||||
|
||||
constructor(
|
||||
private readonly contentScriptName: string,
|
||||
public readonly options?: Omit<ContentScriptDefinition, 'main'>,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.#abortController = new AbortController();
|
||||
if (this.#isTopFrame) {
|
||||
this.#stopOldScripts();
|
||||
}
|
||||
@@ -29,6 +29,14 @@ export class ContentScriptContext extends AbortController {
|
||||
});
|
||||
}
|
||||
|
||||
get signal() {
|
||||
return this.#abortController.signal;
|
||||
}
|
||||
|
||||
abort(reason?: any): void {
|
||||
return this.#abortController.abort(reason);
|
||||
}
|
||||
|
||||
get isInvalid(): boolean {
|
||||
if (browser.runtime.id == null) {
|
||||
this.notifyInvalidated(); // Sets `signal.aborted` to true
|
||||
|
||||
@@ -38,11 +38,10 @@ export async function findEntrypoints(
|
||||
relativePaths.sort();
|
||||
|
||||
const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
|
||||
const existingNames: Record<string, Entrypoint | undefined> = {};
|
||||
|
||||
const entrypoints: Entrypoint[] = [];
|
||||
let hasBackground = false;
|
||||
await Promise.all(
|
||||
// TODO: This parallelization is bad
|
||||
const possibleEntrypoints: Array<Entrypoint | undefined> = await Promise.all(
|
||||
relativePaths.map(async (relativePath) => {
|
||||
const path = resolve(config.entrypointsDir, relativePath);
|
||||
const matchingGlob = pathGlobs.find((glob) =>
|
||||
@@ -50,41 +49,35 @@ export async function findEntrypoints(
|
||||
);
|
||||
|
||||
if (matchingGlob == null) {
|
||||
return config.logger.warn(
|
||||
config.logger.warn(
|
||||
`${relativePath} does not match any known entrypoint. Known entrypoints:\n${JSON.stringify(
|
||||
PATH_GLOB_TO_TYPE_MAP,
|
||||
null,
|
||||
2,
|
||||
)}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
|
||||
if (type === 'ignored') return;
|
||||
|
||||
let entrypoint: Entrypoint;
|
||||
switch (type) {
|
||||
case 'popup':
|
||||
entrypoint = await getPopupEntrypoint(config, path);
|
||||
break;
|
||||
return await getPopupEntrypoint(config, path);
|
||||
case 'options':
|
||||
entrypoint = await getOptionsEntrypoint(config, path);
|
||||
break;
|
||||
return await getOptionsEntrypoint(config, path);
|
||||
case 'background':
|
||||
entrypoint = await getBackgroundEntrypoint(config, path);
|
||||
hasBackground = true;
|
||||
break;
|
||||
return await getBackgroundEntrypoint(config, path);
|
||||
case 'content-script':
|
||||
entrypoint = await getContentScriptEntrypoint(config, path);
|
||||
break;
|
||||
return await getContentScriptEntrypoint(config, path);
|
||||
case 'unlisted-page':
|
||||
entrypoint = await getUnlistedPageEntrypoint(config, path);
|
||||
break;
|
||||
return await getUnlistedPageEntrypoint(config, path);
|
||||
case 'unlisted-script':
|
||||
entrypoint = await getUnlistedScriptEntrypoint(config, path);
|
||||
break;
|
||||
return await getUnlistedScriptEntrypoint(config, path);
|
||||
case 'content-script-style':
|
||||
entrypoint = {
|
||||
return {
|
||||
type,
|
||||
name: getEntrypointName(config.entrypointsDir, path),
|
||||
inputPath: path,
|
||||
@@ -94,9 +87,8 @@ export async function findEntrypoints(
|
||||
exclude: undefined,
|
||||
},
|
||||
};
|
||||
break;
|
||||
default:
|
||||
entrypoint = {
|
||||
return {
|
||||
type,
|
||||
name: getEntrypointName(config.entrypointsDir, path),
|
||||
inputPath: path,
|
||||
@@ -107,22 +99,30 @@ export async function findEntrypoints(
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const withSameName = existingNames[entrypoint.name];
|
||||
if (withSameName) {
|
||||
throw Error(
|
||||
`Multiple entrypoints with the name "${
|
||||
entrypoint.name
|
||||
}" detected, but only one is allowed: ${[
|
||||
relative(config.root, withSameName.inputPath),
|
||||
relative(config.root, entrypoint.inputPath),
|
||||
].join(', ')}`,
|
||||
);
|
||||
}
|
||||
entrypoints.push(entrypoint);
|
||||
existingNames[entrypoint.name] = entrypoint;
|
||||
}),
|
||||
);
|
||||
|
||||
const entrypoints = possibleEntrypoints.filter(
|
||||
(entry) => !!entry,
|
||||
) as Entrypoint[];
|
||||
|
||||
// Report duplicate entrypoint names
|
||||
const existingNames: Record<string, Entrypoint | undefined> = {};
|
||||
entrypoints.forEach((entrypoint) => {
|
||||
const withSameName = existingNames[entrypoint.name];
|
||||
if (withSameName) {
|
||||
throw Error(
|
||||
`Multiple entrypoints with the name "${
|
||||
entrypoint.name
|
||||
}" detected, but only one is allowed: ${[
|
||||
relative(config.root, withSameName.inputPath),
|
||||
relative(config.root, entrypoint.inputPath),
|
||||
].join(', ')}`,
|
||||
);
|
||||
}
|
||||
existingNames[entrypoint.name] = entrypoint;
|
||||
});
|
||||
|
||||
if (config.command === 'serve' && !hasBackground) {
|
||||
entrypoints.push(
|
||||
await getBackgroundEntrypoint(config, VIRTUAL_NOOP_BACKGROUND_MODULE_ID),
|
||||
|
||||
@@ -324,14 +324,10 @@ function addEntrypoints(
|
||||
const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
|
||||
([, scripts]) => ({
|
||||
...mapWxtOptionsToContentScript(scripts[0].options, config),
|
||||
// TOOD: Sorting css and js arrays here so we get consistent test results... but we
|
||||
// shouldn't have to. Where is the inconsistency coming from?
|
||||
css: getContentScriptCssFiles(scripts, cssMap)?.sort(),
|
||||
js: scripts
|
||||
.map((entry) =>
|
||||
getEntrypointBundlePath(entry, config.outDir, '.js'),
|
||||
)
|
||||
.sort(),
|
||||
css: getContentScriptCssFiles(scripts, cssMap),
|
||||
js: scripts.map((entry) =>
|
||||
getEntrypointBundlePath(entry, config.outDir, '.js'),
|
||||
),
|
||||
}),
|
||||
);
|
||||
if (newContentScripts.length >= 0) {
|
||||
|
||||
Reference in New Issue
Block a user