extension-develop 4.0.26 → 4.0.28
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/README.md +5 -1
- package/dist/0~dev-server.mjs +81 -19
- package/dist/0~rspack-config.mjs +399 -184
- package/dist/101.mjs +1099 -972
- package/dist/494.mjs +12 -1
- package/dist/839.mjs +108 -27
- package/dist/bridge.mjs +1 -1
- package/dist/command-preview.d.ts +7 -0
- package/dist/dev-server/control-bridge/controller-client.d.ts +1 -0
- package/dist/dev-server/control-bridge/producer-runtime.d.ts +2 -1
- package/dist/dev-server/index.d.ts +2 -0
- package/dist/extension-js-devtools/chrome/background/service_worker.js +1 -1
- package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/chrome/pages/centralized-logger.css +1 -1
- package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/chrome/pages/welcome.css +1 -1
- package/dist/extension-js-devtools/chromium/background/service_worker.js +1 -1
- package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/chromium/pages/centralized-logger.css +1 -1
- package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/chromium/pages/welcome.css +1 -1
- package/dist/extension-js-devtools/edge/background/service_worker.js +1 -1
- package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/edge/pages/centralized-logger.css +1 -1
- package/dist/extension-js-devtools/edge/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/edge/pages/welcome.css +1 -1
- package/dist/extension-js-devtools/firefox/background/scripts.js +1 -1
- package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/firefox/manifest.json +6 -1
- package/dist/extension-js-devtools/firefox/pages/centralized-logger.css +1 -1
- package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/firefox/pages/welcome.css +1 -1
- package/dist/extension-js-theme/chrome/manifest.json +20 -5
- package/dist/extension-js-theme/chromium/manifest.json +20 -5
- package/dist/extension-js-theme/edge/manifest.json +20 -5
- package/dist/extension-js-theme/firefox/manifest.json +47 -12
- package/dist/feature-scripts-content-script-wrapper.js +2 -1
- package/dist/feature-scripts-content-script-wrapper.mjs +2 -1
- package/dist/lib/atomic-dist.d.ts +5 -0
- package/dist/lib/config-loader.d.ts +12 -12
- package/dist/lib/constants.d.ts +2 -0
- package/dist/lib/merge-options.d.ts +67 -0
- package/dist/lib/paths.d.ts +1 -1
- package/dist/lib/session-paths.d.ts +1 -0
- package/dist/plugin-compilation/boring.d.ts +1 -0
- package/dist/plugin-compilation/zip.d.ts +2 -0
- package/dist/plugin-playwright/index.d.ts +2 -0
- package/dist/plugin-web-extension/feature-html/html-lib/utils.d.ts +2 -1
- package/dist/plugin-web-extension/feature-json/messages.d.ts +2 -0
- package/dist/plugin-web-extension/feature-manifest/manifest-lib/theme-values.d.ts +1 -0
- package/dist/plugin-web-extension/feature-manifest/messages.d.ts +1 -0
- package/dist/plugin-web-extension/feature-manifest/steps/patch-chromium-theme-colors.d.ts +2 -0
- package/dist/plugin-web-extension/feature-web-resources/collect-entry-imports.d.ts +1 -0
- package/dist/types.d.ts +26 -5
- package/package.json +1 -1
package/dist/0~rspack-config.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { filterKeysForThisBrowser as external_browser_extension_manifest_fields_
|
|
|
12
12
|
import content_security_policy_parser from "content-security-policy-parser";
|
|
13
13
|
import node_fs from "node:fs";
|
|
14
14
|
import node_path from "node:path";
|
|
15
|
-
import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, treeWithDistFilesBrowser, packagingDistributionFiles, toPosixPath, resolveCompanionExtensionDirs, debugContextPath, PlaywrightPlugin,
|
|
15
|
+
import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, treeWithDistFilesBrowser, packagingDistributionFiles, toPosixPath, resolveCompanionExtensionDirs, debugContextPath, PlaywrightPlugin, isWebkitBasedBrowser, spacerLine, isGeckoBasedBrowser, messages_ready, CHROMIUM_FAMILY_ALIASES, treeWithSourceAndDistFiles, computeExtensionsToLoad, noCompanionExtensionsResolved, treeWithSourceFiles, bundlerFatalError, bundlerRecompiling, noEntrypointsDetected, GECKO_FAMILY_ALIASES, packagingSourceFiles, debugBrowser, debugOutputPath, manifestInvalidJson, isChromiumBasedBrowser, getSpecialFoldersDataForCompiler } from "./101.mjs";
|
|
16
16
|
import { stripBom, parseJsonSafe } from "./23.mjs";
|
|
17
17
|
import { isResourceUnderDirs, canonicalizeDir, toResourceKey } from "./93.mjs";
|
|
18
18
|
import { prefix as messaging_prefix, isDebug } from "./349.mjs";
|
|
@@ -377,6 +377,7 @@ class BoringPlugin {
|
|
|
377
377
|
browser;
|
|
378
378
|
sawUserInvalidation = false;
|
|
379
379
|
printedStartupSuccess = false;
|
|
380
|
+
printedStartupWarning = false;
|
|
380
381
|
lastKnownManifestName;
|
|
381
382
|
constructor(options){
|
|
382
383
|
this.manifestPath = options.manifestPath;
|
|
@@ -386,6 +387,7 @@ class BoringPlugin {
|
|
|
386
387
|
compiler.hooks.watchClose.tap('develop:brand:watch-close', ()=>{
|
|
387
388
|
this.sawUserInvalidation = false;
|
|
388
389
|
this.printedStartupSuccess = false;
|
|
390
|
+
this.printedStartupWarning = false;
|
|
389
391
|
});
|
|
390
392
|
compiler.hooks.done.tap('develop:brand', (stats)=>{
|
|
391
393
|
const hasErrors = Boolean(stats?.hasErrors?.());
|
|
@@ -396,8 +398,10 @@ class BoringPlugin {
|
|
|
396
398
|
let manifestName;
|
|
397
399
|
try {
|
|
398
400
|
const parsedName = parseJsonSafe(__rspack_external_node_fs_5ea92f0c.readFileSync(this.manifestPath, 'utf-8')).name;
|
|
399
|
-
if ('string' == typeof parsedName && parsedName)
|
|
400
|
-
|
|
401
|
+
if ('string' == typeof parsedName && parsedName) {
|
|
402
|
+
this.lastKnownManifestName = parsedName;
|
|
403
|
+
manifestName = parsedName;
|
|
404
|
+
} else manifestName = this.lastKnownManifestName;
|
|
401
405
|
} catch {
|
|
402
406
|
manifestName = this.lastKnownManifestName;
|
|
403
407
|
}
|
|
@@ -413,16 +417,22 @@ class BoringPlugin {
|
|
|
413
417
|
].map((file)=>String(file).replace(/\\/g, '/'));
|
|
414
418
|
if (!this.sawUserInvalidation && modifiedFiles.length > 0) {
|
|
415
419
|
const context = String(compiler?.options?.context || '').replace(/\\/g, '/');
|
|
420
|
+
const outputPath = String(compiler?.options?.output?.path || '').replace(/\\/g, '/');
|
|
421
|
+
const distRoot = context ? `${context}/dist` : '';
|
|
422
|
+
const isUnderRoot = (file, root)=>'' !== root && (file === root || file.startsWith(`${root}/`));
|
|
416
423
|
const hasUserFileChange = modifiedFiles.some((file)=>{
|
|
417
424
|
const inProject = !context || file.startsWith(`${context}/`);
|
|
418
|
-
const isGenerated = file
|
|
425
|
+
const isGenerated = isUnderRoot(file, outputPath) || isUnderRoot(file, distRoot) || file.includes('/extension-js/profiles/');
|
|
419
426
|
return inProject && !isGenerated;
|
|
420
427
|
});
|
|
421
428
|
if (hasUserFileChange) this.sawUserInvalidation = true;
|
|
422
429
|
}
|
|
423
|
-
if (browserLaunchEnabled && !hasErrors && !hasWarnings) {
|
|
424
|
-
if (
|
|
425
|
-
|
|
430
|
+
if (browserLaunchEnabled && !hasErrors && !this.sawUserInvalidation) if (hasWarnings) {
|
|
431
|
+
if (this.printedStartupWarning) return;
|
|
432
|
+
this.printedStartupWarning = true;
|
|
433
|
+
} else {
|
|
434
|
+
if (this.printedStartupSuccess) return;
|
|
435
|
+
this.printedStartupSuccess = true;
|
|
426
436
|
}
|
|
427
437
|
humanLine(line);
|
|
428
438
|
} catch {}
|
|
@@ -436,7 +446,8 @@ class CleanDistFolderPlugin {
|
|
|
436
446
|
}
|
|
437
447
|
apply(compiler) {
|
|
438
448
|
const logger = compiler.getInfrastructureLogger('plugin-compilation:clean');
|
|
439
|
-
const
|
|
449
|
+
const configuredOutputPath = compiler.options.output?.path;
|
|
450
|
+
const distPath = 'string' == typeof configuredOutputPath && configuredOutputPath ? configuredOutputPath : __rspack_external_node_path_c5b9b54f.join(compiler.options.context, 'dist', this.options.browser);
|
|
440
451
|
if (__rspack_external_node_fs_5ea92f0c.existsSync(distPath)) {
|
|
441
452
|
const removedCount = countFilesRecursively(distPath);
|
|
442
453
|
if (isDebug()) console.log(cleanDistStarting(distPath));
|
|
@@ -1054,8 +1065,15 @@ function getManifestOverrides(manifestPath, manifest) {
|
|
|
1054
1065
|
return JSON.stringify(merged, null, 2);
|
|
1055
1066
|
}
|
|
1056
1067
|
const manifest_cjsRequire = createRequire(import.meta.url);
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1068
|
+
const manifestSourceStore = new WeakMap();
|
|
1069
|
+
function manifestSourceEntry(compilation) {
|
|
1070
|
+
let entry = manifestSourceStore.get(compilation);
|
|
1071
|
+
if (!entry) {
|
|
1072
|
+
entry = {};
|
|
1073
|
+
manifestSourceStore.set(compilation, entry);
|
|
1074
|
+
}
|
|
1075
|
+
return entry;
|
|
1076
|
+
}
|
|
1059
1077
|
function readAssetSource(asset) {
|
|
1060
1078
|
if (!asset) return '';
|
|
1061
1079
|
const source = asset.source;
|
|
@@ -1071,16 +1089,16 @@ function readAssetSource(asset) {
|
|
|
1071
1089
|
return '';
|
|
1072
1090
|
}
|
|
1073
1091
|
function setOriginalManifestContent(compilation, source) {
|
|
1074
|
-
compilation
|
|
1092
|
+
manifestSourceEntry(compilation).original = source;
|
|
1075
1093
|
}
|
|
1076
1094
|
function getOriginalManifestContent(compilation) {
|
|
1077
|
-
return compilation
|
|
1095
|
+
return manifestSourceStore.get(compilation)?.original;
|
|
1078
1096
|
}
|
|
1079
1097
|
function setCurrentManifestContent(compilation, source) {
|
|
1080
|
-
compilation
|
|
1098
|
+
manifestSourceEntry(compilation).current = source;
|
|
1081
1099
|
}
|
|
1082
1100
|
function getCurrentManifestContent(compilation) {
|
|
1083
|
-
return compilation
|
|
1101
|
+
return manifestSourceStore.get(compilation)?.current;
|
|
1084
1102
|
}
|
|
1085
1103
|
function getManifestContent(compilation, manifestPath) {
|
|
1086
1104
|
const currentManifest = getCurrentManifestContent(compilation);
|
|
@@ -1305,6 +1323,23 @@ function isCompanionExtension(file) {
|
|
|
1305
1323
|
const [first] = toPosix(file).split('/');
|
|
1306
1324
|
return first === COMPANION_DIR;
|
|
1307
1325
|
}
|
|
1326
|
+
const DENIED_SEGMENTS = new Set([
|
|
1327
|
+
'.git',
|
|
1328
|
+
'.extension-js',
|
|
1329
|
+
'node_modules'
|
|
1330
|
+
]);
|
|
1331
|
+
const SESSION_ARTIFACTS_PREFIX = 'dist/extension-js';
|
|
1332
|
+
function isDeniedEnvFile(basename) {
|
|
1333
|
+
if (!basename.startsWith('.env')) return false;
|
|
1334
|
+
return !basename.endsWith('.example');
|
|
1335
|
+
}
|
|
1336
|
+
function isDeniedFromSourceZip(file) {
|
|
1337
|
+
const posix = toPosix(file);
|
|
1338
|
+
const segments = posix.split('/');
|
|
1339
|
+
if (segments.some((segment)=>DENIED_SEGMENTS.has(segment))) return true;
|
|
1340
|
+
if (isDeniedEnvFile(segments[segments.length - 1])) return true;
|
|
1341
|
+
return posix === SESSION_ARTIFACTS_PREFIX || posix.startsWith(`${SESSION_ARTIFACTS_PREFIX}/`);
|
|
1342
|
+
}
|
|
1308
1343
|
async function getFilesToZip(projectDir) {
|
|
1309
1344
|
const gitignorePath = __rspack_external_node_path_c5b9b54f.join(projectDir, '.gitignore');
|
|
1310
1345
|
const ig = ignore();
|
|
@@ -1314,9 +1349,11 @@ async function getFilesToZip(projectDir) {
|
|
|
1314
1349
|
} catch {}
|
|
1315
1350
|
const files = await tiny_glob('**/*', {
|
|
1316
1351
|
cwd: projectDir,
|
|
1317
|
-
dot: true
|
|
1352
|
+
dot: true,
|
|
1353
|
+
filesOnly: true,
|
|
1354
|
+
flush: true
|
|
1318
1355
|
});
|
|
1319
|
-
return files.filter((file)=>!ig.ignores(file) && !isCompanionExtension(file));
|
|
1356
|
+
return files.filter((file)=>!isDeniedFromSourceZip(file) && !ig.ignores(file) && !isCompanionExtension(file));
|
|
1320
1357
|
}
|
|
1321
1358
|
class ZipPlugin {
|
|
1322
1359
|
options;
|
|
@@ -2928,7 +2965,7 @@ const cloneParsedHtmlAsset = (assets)=>({
|
|
|
2928
2965
|
]
|
|
2929
2966
|
});
|
|
2930
2967
|
const assetsFromHtmlCache = new Map();
|
|
2931
|
-
function getAssetsFromHtml(htmlFilePath, htmlContent
|
|
2968
|
+
function getAssetsFromHtml(htmlFilePath, htmlContent) {
|
|
2932
2969
|
const assets = {
|
|
2933
2970
|
css: [],
|
|
2934
2971
|
js: [],
|
|
@@ -2939,7 +2976,7 @@ function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
|
|
|
2939
2976
|
let cacheKey;
|
|
2940
2977
|
if (void 0 === htmlContent) try {
|
|
2941
2978
|
const stat = __rspack_external_node_fs_5ea92f0c.statSync(htmlFilePath);
|
|
2942
|
-
cacheKey = `${stat.mtimeMs}:${stat.size}
|
|
2979
|
+
cacheKey = `${stat.mtimeMs}:${stat.size}`;
|
|
2943
2980
|
const cached = assetsFromHtmlCache.get(htmlFilePath);
|
|
2944
2981
|
if (cached && cached.key === cacheKey) return cloneParsedHtmlAsset(cached.assets);
|
|
2945
2982
|
} catch {
|
|
@@ -2983,6 +3020,11 @@ function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
|
|
|
2983
3020
|
}
|
|
2984
3021
|
});
|
|
2985
3022
|
} catch (error) {
|
|
3023
|
+
const code = error?.code;
|
|
3024
|
+
if (void 0 === htmlContent && 'ENOENT' === code) {
|
|
3025
|
+
assetsFromHtmlCache.delete(htmlFilePath);
|
|
3026
|
+
throw error;
|
|
3027
|
+
}
|
|
2986
3028
|
return assets;
|
|
2987
3029
|
}
|
|
2988
3030
|
if (cacheKey) assetsFromHtmlCache.set(htmlFilePath, {
|
|
@@ -2995,6 +3037,7 @@ function getHtmlPageDeclaredAssetPath(filepathList, filePath, extension) {
|
|
|
2995
3037
|
const entryname = Object.keys(filepathList).find((key)=>{
|
|
2996
3038
|
const includePath = filepathList[key];
|
|
2997
3039
|
if (includePath === filePath) return true;
|
|
3040
|
+
if (!includePath || !__rspack_external_node_fs_5ea92f0c.existsSync(includePath)) return false;
|
|
2998
3041
|
const assets = getAssetsFromHtml(includePath);
|
|
2999
3042
|
return Boolean(assets?.js?.includes(filePath) || assets?.css?.includes(filePath));
|
|
3000
3043
|
}) || '';
|
|
@@ -3872,6 +3915,7 @@ class PerfBudgetsPlugin {
|
|
|
3872
3915
|
});
|
|
3873
3916
|
}
|
|
3874
3917
|
}
|
|
3918
|
+
const CONTROL_PORT_ASSET_NAME = 'extension-js-control.json';
|
|
3875
3919
|
const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
3876
3920
|
try {
|
|
3877
3921
|
var g = (typeof globalThis === "object" && globalThis) ? globalThis : this;
|
|
@@ -3913,12 +3957,24 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3913
3957
|
} catch (e) { /* non-fatal: trigger falls back to its no-listener reply */ }
|
|
3914
3958
|
}
|
|
3915
3959
|
|
|
3916
|
-
// Use
|
|
3960
|
+
// Use the raw globals (not the hoisted chrome var below). This runs first.
|
|
3961
|
+
// On Gecko browser.* is a DISTINCT wrapper object: hook BOTH namespaces.
|
|
3917
3962
|
var actionClickedListeners = [];
|
|
3918
3963
|
var commandListeners = [];
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3964
|
+
var capturedEvents = [];
|
|
3965
|
+
function captureEventOnce(event, sink) {
|
|
3966
|
+
// Polyfilled extensions expose ONE event object on both namespaces:
|
|
3967
|
+
// wrap it once, and the sink dedupes callbacks shared across wrappers.
|
|
3968
|
+
if (!event || capturedEvents.indexOf(event) !== -1) return;
|
|
3969
|
+
capturedEvents.push(event);
|
|
3970
|
+
captureEvent(event, sink);
|
|
3971
|
+
}
|
|
3972
|
+
var captureNamespaces = [g.chrome, g.browser];
|
|
3973
|
+
for (var cn = 0; cn < captureNamespaces.length; cn++) {
|
|
3974
|
+
var capNS = captureNamespaces[cn];
|
|
3975
|
+
if (!capNS) continue;
|
|
3976
|
+
captureEventOnce(capNS.action && capNS.action.onClicked, actionClickedListeners);
|
|
3977
|
+
captureEventOnce(capNS.commands && capNS.commands.onCommand, commandListeners);
|
|
3922
3978
|
}
|
|
3923
3979
|
|
|
3924
3980
|
var LEVELS = ["log", "info", "warn", "error", "debug", "trace"];
|
|
@@ -3927,6 +3983,7 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3927
3983
|
var queue = [];
|
|
3928
3984
|
var backoff = 250;
|
|
3929
3985
|
var MAX_BACKOFF = 5000;
|
|
3986
|
+
var connectFailures = 0;
|
|
3930
3987
|
var MAX_QUEUE = 1000;
|
|
3931
3988
|
var MAX_RESULT_BYTES = 256 * 1024;
|
|
3932
3989
|
|
|
@@ -4695,10 +4752,36 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
4695
4752
|
if (queue.length < MAX_QUEUE) queue.push(frame);
|
|
4696
4753
|
}
|
|
4697
4754
|
|
|
4755
|
+
// The baked PORT is a snapshot of an ephemeral port. After a dev-server
|
|
4756
|
+
// restart, the port file shipped in the unpacked extension names the
|
|
4757
|
+
// live one, and unpacked resources are read from disk on every fetch.
|
|
4758
|
+
function refreshControlPort(done) {
|
|
4759
|
+
try {
|
|
4760
|
+
var runtime = (g.chrome && g.chrome.runtime) || (g.browser && g.browser.runtime);
|
|
4761
|
+
if (!runtime || typeof runtime.getURL !== "function" || typeof g.fetch !== "function") { done(); return; }
|
|
4762
|
+
g.fetch(runtime.getURL("extension-js-control.json"), {cache: "no-store"})
|
|
4763
|
+
.then(function (res) { return res.json(); })
|
|
4764
|
+
.then(function (data) {
|
|
4765
|
+
var next = data && parseInt(data.port, 10);
|
|
4766
|
+
if (next && next > 0 && next < 65536 && next !== PORT) PORT = next;
|
|
4767
|
+
done();
|
|
4768
|
+
})
|
|
4769
|
+
.catch(function () { done(); });
|
|
4770
|
+
} catch (e) { done(); }
|
|
4771
|
+
}
|
|
4772
|
+
|
|
4698
4773
|
function schedule() {
|
|
4699
4774
|
var delay = backoff;
|
|
4700
4775
|
backoff = Math.min(backoff * 2, MAX_BACKOFF);
|
|
4701
|
-
|
|
4776
|
+
connectFailures++;
|
|
4777
|
+
try {
|
|
4778
|
+
setTimeout(function () {
|
|
4779
|
+
// Two straight failures make the baked port suspect (a restarted
|
|
4780
|
+
// server dials out on a new port): re-resolve before re-dialing.
|
|
4781
|
+
if (connectFailures >= 2) refreshControlPort(connect);
|
|
4782
|
+
else connect();
|
|
4783
|
+
}, delay);
|
|
4784
|
+
} catch (e) {
|
|
4702
4785
|
// Ignore
|
|
4703
4786
|
}
|
|
4704
4787
|
}
|
|
@@ -4713,6 +4796,7 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
4713
4796
|
socket.onopen = function () {
|
|
4714
4797
|
open = true;
|
|
4715
4798
|
backoff = 250;
|
|
4799
|
+
connectFailures = 0;
|
|
4716
4800
|
try {
|
|
4717
4801
|
socket.send(JSON.stringify({type: "hello", v: 1, role: "producer", instanceId: INSTANCE_ID}));
|
|
4718
4802
|
} catch (e) {
|
|
@@ -5171,6 +5255,10 @@ class InjectBridgeProducer {
|
|
|
5171
5255
|
name: InjectBridgeProducer.name,
|
|
5172
5256
|
stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 101
|
|
5173
5257
|
}, ()=>{
|
|
5258
|
+
if (!compilation.getAsset(CONTROL_PORT_ASSET_NAME)) compilation.emitAsset(CONTROL_PORT_ASSET_NAME, new core_sources.RawSource(JSON.stringify({
|
|
5259
|
+
port: controlPort,
|
|
5260
|
+
instanceId
|
|
5261
|
+
})));
|
|
5174
5262
|
for (const asset of compilation.getAssets()){
|
|
5175
5263
|
if (!BACKGROUND_ASSET.test(asset.name)) continue;
|
|
5176
5264
|
const original = asset.source.source().toString();
|
|
@@ -7485,31 +7573,29 @@ class StaticAssetsPlugin {
|
|
|
7485
7573
|
}
|
|
7486
7574
|
}
|
|
7487
7575
|
};
|
|
7488
|
-
const
|
|
7576
|
+
const isFullCustomRuleFor = (thisRule, sample)=>{
|
|
7489
7577
|
const rule = thisRule;
|
|
7490
|
-
return Boolean(rule && rule.test instanceof RegExp && rule.test.test(
|
|
7491
|
-
}
|
|
7578
|
+
return Boolean(rule && rule.test instanceof RegExp && rule.test.test(sample) && (void 0 !== rule.type || void 0 !== rule.use) && void 0 === rule.resourceQuery);
|
|
7579
|
+
};
|
|
7580
|
+
const scopedQueriesFor = (sample)=>compiler.options.module.rules.map((thisRule)=>thisRule).filter((rule)=>Boolean(rule && rule.test instanceof RegExp && rule.test.test(sample) && (void 0 !== rule.type || void 0 !== rule.use) && rule.resourceQuery instanceof RegExp)).map((rule)=>rule?.resourceQuery);
|
|
7581
|
+
const hasCustomSvgRule = compiler.options.module.rules.some((thisRule)=>isFullCustomRuleFor(thisRule, '.svg'));
|
|
7492
7582
|
const hasUrlResourceQueryRule = compiler.options.module.rules.some((thisRule)=>{
|
|
7493
7583
|
const rule = thisRule;
|
|
7494
7584
|
const resourceQuery = rule?.resourceQuery;
|
|
7495
7585
|
if (!(resourceQuery instanceof RegExp)) return false;
|
|
7496
7586
|
return resourceQuery.test('?url');
|
|
7497
7587
|
});
|
|
7498
|
-
const hasCustomFontsRule = compiler.options.module.rules.some((thisRule)=>
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
if (!rule.test.test('.woff')) return false;
|
|
7502
|
-
return void 0 !== rule.type || void 0 !== rule.use;
|
|
7503
|
-
});
|
|
7588
|
+
const hasCustomFontsRule = compiler.options.module.rules.some((thisRule)=>isFullCustomRuleFor(thisRule, '.woff'));
|
|
7589
|
+
const svgScopedQueries = scopedQueriesFor('.svg');
|
|
7590
|
+
const fontsScopedQueries = scopedQueriesFor('.woff');
|
|
7504
7591
|
const loaders = [
|
|
7505
|
-
...hasUrlResourceQueryRule ? [] : [
|
|
7506
|
-
{
|
|
7507
|
-
resourceQuery: /(?:^\?|&)url(?:&|=|$)/,
|
|
7508
|
-
type: 'asset/resource'
|
|
7509
|
-
}
|
|
7510
|
-
],
|
|
7511
7592
|
...hasCustomSvgRule ? [] : [
|
|
7512
|
-
|
|
7593
|
+
svgScopedQueries.length ? {
|
|
7594
|
+
...defaultSvgRule,
|
|
7595
|
+
resourceQuery: {
|
|
7596
|
+
not: svgScopedQueries
|
|
7597
|
+
}
|
|
7598
|
+
} : defaultSvgRule
|
|
7513
7599
|
],
|
|
7514
7600
|
{
|
|
7515
7601
|
test: /\.(png|jpg|jpeg|gif|webp|avif|ico|bmp)$/i,
|
|
@@ -7529,7 +7615,12 @@ class StaticAssetsPlugin {
|
|
|
7529
7615
|
type: 'asset',
|
|
7530
7616
|
generator: {
|
|
7531
7617
|
filename: filenamePattern
|
|
7532
|
-
}
|
|
7618
|
+
},
|
|
7619
|
+
...fontsScopedQueries.length ? {
|
|
7620
|
+
resourceQuery: {
|
|
7621
|
+
not: fontsScopedQueries
|
|
7622
|
+
}
|
|
7623
|
+
} : {}
|
|
7533
7624
|
}
|
|
7534
7625
|
],
|
|
7535
7626
|
{
|
|
@@ -7543,7 +7634,16 @@ class StaticAssetsPlugin {
|
|
|
7543
7634
|
maxSize: 2048
|
|
7544
7635
|
}
|
|
7545
7636
|
}
|
|
7546
|
-
}
|
|
7637
|
+
},
|
|
7638
|
+
...hasUrlResourceQueryRule ? [] : [
|
|
7639
|
+
{
|
|
7640
|
+
resourceQuery: /(?:^\?|&)url(?:&|=|$)/,
|
|
7641
|
+
type: 'asset/resource',
|
|
7642
|
+
generator: {
|
|
7643
|
+
filename: filenamePattern
|
|
7644
|
+
}
|
|
7645
|
+
}
|
|
7646
|
+
]
|
|
7547
7647
|
];
|
|
7548
7648
|
compiler.options.module.rules = [
|
|
7549
7649
|
...compiler.options.module.rules,
|
|
@@ -8347,9 +8447,9 @@ class AddToFileDependencies {
|
|
|
8347
8447
|
for (const field of Object.entries(allEntries)){
|
|
8348
8448
|
const [, resource] = field;
|
|
8349
8449
|
if (resource) {
|
|
8350
|
-
const resourceData = getAssetsFromHtml(resource);
|
|
8351
8450
|
const fileDependencies = new Set(compilation.fileDependencies);
|
|
8352
8451
|
if (__rspack_external_node_fs_5ea92f0c.existsSync(resource)) {
|
|
8452
|
+
const resourceData = getAssetsFromHtml(resource);
|
|
8353
8453
|
const fileResources = [
|
|
8354
8454
|
resource,
|
|
8355
8455
|
...resourceData?.static || []
|
|
@@ -8576,8 +8676,9 @@ class ThrowIfRecompileIsNeeded {
|
|
|
8576
8676
|
if (changedFile && this.initialHtmlAssets[changedFile]) {
|
|
8577
8677
|
const isRemoteUrl = (p)=>/^(https?:)?\/\//i.test(p);
|
|
8578
8678
|
const looksLikePublicRootUrl = (p)=>p.startsWith('/') && !__rspack_external_node_fs_5ea92f0c.existsSync(p);
|
|
8579
|
-
const
|
|
8580
|
-
const
|
|
8679
|
+
const updatedAssets = __rspack_external_node_fs_5ea92f0c.existsSync(changedFile) ? getAssetsFromHtml(changedFile) : void 0;
|
|
8680
|
+
const updatedJsEntries = (updatedAssets?.js || []).filter((p)=>!looksLikePublicRootUrl(p) && !isRemoteUrl(p));
|
|
8681
|
+
const updatedCssEntries = (updatedAssets?.css || []).filter((p)=>!looksLikePublicRootUrl(p) && !isRemoteUrl(p));
|
|
8581
8682
|
const { js, css } = this.initialHtmlAssets[changedFile];
|
|
8582
8683
|
if (this.hasEntriesChanged(updatedCssEntries, css) || this.hasEntriesChanged(updatedJsEntries, js)) {
|
|
8583
8684
|
const projectRoot = __rspack_external_node_path_c5b9b54f.dirname(this.manifestPath);
|
|
@@ -8985,6 +9086,24 @@ function invalidRulesetStructure(manifestField, file) {
|
|
|
8985
9086
|
"Update the file to contain an array of rules."
|
|
8986
9087
|
].join('\n');
|
|
8987
9088
|
}
|
|
9089
|
+
function invalidRulesetRule(manifestField, file, ruleIndex, reason) {
|
|
9090
|
+
return [
|
|
9091
|
+
`The Declarative Net Request ruleset listed in ${pintor.blue(manifestField)} has a rule Chrome rejects at load.`,
|
|
9092
|
+
`${pintor.gray('PATH')} ${pintor.underline(file)}`,
|
|
9093
|
+
`${pintor.gray('RULE')} ${pintor.underline(`index ${ruleIndex}`)}`,
|
|
9094
|
+
`${pintor.gray('REASON')} ${pintor.underline(reason)}`,
|
|
9095
|
+
"Give every rule an integer id of 1 or more, an action with a type, and a condition object."
|
|
9096
|
+
].join('\n');
|
|
9097
|
+
}
|
|
9098
|
+
function rulesetRuleShapeIssue(manifestField, file, ruleIndex, reason) {
|
|
9099
|
+
return [
|
|
9100
|
+
`A rule in the Declarative Net Request ruleset listed in ${pintor.blue(manifestField)} may not behave as intended.`,
|
|
9101
|
+
`${pintor.gray('PATH')} ${pintor.underline(file)}`,
|
|
9102
|
+
`${pintor.gray('RULE')} ${pintor.underline(`index ${ruleIndex}`)}`,
|
|
9103
|
+
`${pintor.gray('REASON')} ${pintor.underline(reason)}`,
|
|
9104
|
+
`Check the rule against the Declarative Net Request rule schema.\nThe build continues.`
|
|
9105
|
+
].join('\n');
|
|
9106
|
+
}
|
|
8988
9107
|
function invalidManagedSchemaStructure(manifestField, file) {
|
|
8989
9108
|
return [
|
|
8990
9109
|
`The managed storage schema listed in ${pintor.blue(manifestField)} isn't a schema object.`,
|
|
@@ -9005,6 +9124,22 @@ function jsonIncludeSummary(totalFeatures, criticalCount) {
|
|
|
9005
9124
|
function isCriticalJsonFeature(feature) {
|
|
9006
9125
|
return feature.startsWith('declarative_net_request') || 'storage.managed_schema' === feature;
|
|
9007
9126
|
}
|
|
9127
|
+
function isPlainObject(value) {
|
|
9128
|
+
return 'object' == typeof value && null !== value && !Array.isArray(value);
|
|
9129
|
+
}
|
|
9130
|
+
function getDnrRuleRejection(rule) {
|
|
9131
|
+
if (!isPlainObject(rule)) return 'the rule is not an object';
|
|
9132
|
+
const id = rule.id;
|
|
9133
|
+
if ('number' != typeof id || !Number.isInteger(id) || id < 1) return 'the rule id is not a positive integer';
|
|
9134
|
+
const action = rule.action;
|
|
9135
|
+
if (!isPlainObject(action)) return 'the rule has no action object';
|
|
9136
|
+
if ('string' != typeof action.type || 0 === action.type.length) return 'the rule action has no type';
|
|
9137
|
+
if (!isPlainObject(rule.condition)) return 'the rule has no condition object';
|
|
9138
|
+
}
|
|
9139
|
+
function getDnrRuleSoftIssue(rule) {
|
|
9140
|
+
const priority = rule.priority;
|
|
9141
|
+
if (void 0 !== priority && ('number' != typeof priority || !Number.isInteger(priority) || priority < 1)) return 'the rule priority is not a positive integer';
|
|
9142
|
+
}
|
|
9008
9143
|
function validateJsonAsset(compilation, feature, filePath, buf) {
|
|
9009
9144
|
let parsed;
|
|
9010
9145
|
try {
|
|
@@ -9024,6 +9159,23 @@ function validateJsonAsset(compilation, feature, filePath, buf) {
|
|
|
9024
9159
|
compilation.errors.push(err);
|
|
9025
9160
|
return false;
|
|
9026
9161
|
}
|
|
9162
|
+
for(let index = 0; index < parsed.length; index++){
|
|
9163
|
+
const rejection = getDnrRuleRejection(parsed[index]);
|
|
9164
|
+
if (rejection) {
|
|
9165
|
+
const err = new core_WebpackError(invalidRulesetRule(feature, filePath, index, rejection));
|
|
9166
|
+
err.file = filePath;
|
|
9167
|
+
err.name = 'DNRInvalidRule';
|
|
9168
|
+
compilation.errors.push(err);
|
|
9169
|
+
return false;
|
|
9170
|
+
}
|
|
9171
|
+
const softIssue = getDnrRuleSoftIssue(parsed[index]);
|
|
9172
|
+
if (softIssue) {
|
|
9173
|
+
const warn = new core_WebpackError(rulesetRuleShapeIssue(feature, filePath, index, softIssue));
|
|
9174
|
+
warn.file = filePath;
|
|
9175
|
+
warn.name = 'DNRRuleShapeIssue';
|
|
9176
|
+
compilation.warnings.push(warn);
|
|
9177
|
+
}
|
|
9178
|
+
}
|
|
9027
9179
|
} else if ('storage.managed_schema' === feature) {
|
|
9028
9180
|
if (null === parsed || Array.isArray(parsed) || 'object' != typeof parsed) {
|
|
9029
9181
|
const err = new core_WebpackError(invalidManagedSchemaStructure(feature, filePath));
|
|
@@ -9462,6 +9614,12 @@ function invalidThemeValue(field, detail, value) {
|
|
|
9462
9614
|
lines.push(`${pintor.red('INVALID VALUE')} ${value}`);
|
|
9463
9615
|
return lines.join('\n');
|
|
9464
9616
|
}
|
|
9617
|
+
function themeNotSupportedByBrowser(browser) {
|
|
9618
|
+
const lines = [];
|
|
9619
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.blue(browser)} does not support the ${pintor.yellow('theme')} field.`);
|
|
9620
|
+
lines.push("The field ships unchanged in the manifest and Safari ignores it.");
|
|
9621
|
+
return lines.join('\n');
|
|
9622
|
+
}
|
|
9465
9623
|
function missingGeckoDataCollectionPermissions() {
|
|
9466
9624
|
const lines = [];
|
|
9467
9625
|
lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.blue('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
|
|
@@ -9933,6 +10091,99 @@ class ManifestLegacyWarnings {
|
|
|
9933
10091
|
});
|
|
9934
10092
|
}
|
|
9935
10093
|
}
|
|
10094
|
+
const EMITTED_ASSET_REF_PATTERN = /assets\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*/g;
|
|
10095
|
+
function forEachStringKey(objectOrMap, callback) {
|
|
10096
|
+
if (!objectOrMap) return;
|
|
10097
|
+
if (objectOrMap instanceof Map) {
|
|
10098
|
+
const keys = objectOrMap.keys();
|
|
10099
|
+
for (const key of keys)callback(String(key));
|
|
10100
|
+
} else if ('object' == typeof objectOrMap) {
|
|
10101
|
+
const objectKeys = Object.keys(objectOrMap);
|
|
10102
|
+
for (const key of objectKeys)callback(key);
|
|
10103
|
+
}
|
|
10104
|
+
}
|
|
10105
|
+
function getAssetSource(compilation, filename) {
|
|
10106
|
+
let assetGetFunction;
|
|
10107
|
+
if ('function' == typeof compilation.getAsset) assetGetFunction = compilation.getAsset(filename);
|
|
10108
|
+
let assetViaAssets;
|
|
10109
|
+
if (!assetGetFunction && compilation.assets) assetViaAssets = compilation.assets[filename];
|
|
10110
|
+
const asset = assetGetFunction || assetViaAssets;
|
|
10111
|
+
if (!asset) return '';
|
|
10112
|
+
let src;
|
|
10113
|
+
src = 'function' == typeof asset.source ? asset.source() : asset.source?.source ? asset.source.source() : asset.source;
|
|
10114
|
+
if ('string' == typeof src) return src;
|
|
10115
|
+
return '';
|
|
10116
|
+
}
|
|
10117
|
+
function collectContentScriptEntryImports(compilation, includeList) {
|
|
10118
|
+
const entryImports = {};
|
|
10119
|
+
const contentEntryNames = new Set(Object.keys(includeList || {}).filter((k)=>k.startsWith("content_scripts")));
|
|
10120
|
+
const chunkGraph = compilation.chunkGraph;
|
|
10121
|
+
compilation.entrypoints.forEach((_entry, entryName)=>{
|
|
10122
|
+
if (String(entryName).startsWith("content_scripts/")) contentEntryNames.add(entryName);
|
|
10123
|
+
});
|
|
10124
|
+
compilation.entrypoints.forEach((entry, entryName)=>{
|
|
10125
|
+
if (!contentEntryNames.has(entryName)) return;
|
|
10126
|
+
const collectedFilesSet = new Set();
|
|
10127
|
+
function addFileIfRelevant(file) {
|
|
10128
|
+
if (null == file) return;
|
|
10129
|
+
const fileNameStr = String(file);
|
|
10130
|
+
const isJavaScript = fileNameStr.endsWith('.js');
|
|
10131
|
+
const isSourceMap = fileNameStr.endsWith('.map');
|
|
10132
|
+
if (isJavaScript || isSourceMap) return;
|
|
10133
|
+
collectedFilesSet.add(fileNameStr);
|
|
10134
|
+
}
|
|
10135
|
+
entry.chunks.forEach((chunk)=>{
|
|
10136
|
+
const currentChunk = chunk;
|
|
10137
|
+
const chunkFilesArray = Array.isArray(currentChunk.files) ? currentChunk.files : [];
|
|
10138
|
+
for(let i = 0; i < chunkFilesArray.length; i++)addFileIfRelevant(chunkFilesArray[i]);
|
|
10139
|
+
let chunkAuxFilesArray = [];
|
|
10140
|
+
if (Array.isArray(currentChunk.auxiliaryFiles)) chunkAuxFilesArray = currentChunk.auxiliaryFiles;
|
|
10141
|
+
for(let i = 0; i < chunkAuxFilesArray.length; i++)addFileIfRelevant(chunkAuxFilesArray[i]);
|
|
10142
|
+
const modulesArray = Array.from(chunkGraph.getChunkModulesIterable(chunk));
|
|
10143
|
+
for(let j = 0; j < modulesArray.length; j++){
|
|
10144
|
+
const moduleObj = modulesArray[j];
|
|
10145
|
+
const moduleChunksArray = Array.from(chunkGraph.getModuleChunks(moduleObj));
|
|
10146
|
+
for(let k = 0; k < moduleChunksArray.length; k++){
|
|
10147
|
+
const mk = moduleChunksArray[k];
|
|
10148
|
+
const mkAuxFilesArr = Array.isArray(mk.auxiliaryFiles) ? mk.auxiliaryFiles : [];
|
|
10149
|
+
for(let l = 0; l < mkAuxFilesArr.length; l++)addFileIfRelevant(mkAuxFilesArr[l]);
|
|
10150
|
+
}
|
|
10151
|
+
const moduleWithBuildInfo = moduleObj;
|
|
10152
|
+
const buildInfo = moduleWithBuildInfo.buildInfo;
|
|
10153
|
+
forEachStringKey(buildInfo?.assets, (key)=>{
|
|
10154
|
+
addFileIfRelevant(key);
|
|
10155
|
+
});
|
|
10156
|
+
forEachStringKey(buildInfo?.assetsInfo, (key)=>{
|
|
10157
|
+
addFileIfRelevant(key);
|
|
10158
|
+
});
|
|
10159
|
+
}
|
|
10160
|
+
for(let i = 0; i < chunkFilesArray.length; i++){
|
|
10161
|
+
const chunkFileName = chunkFilesArray[i];
|
|
10162
|
+
if (!String(chunkFileName).endsWith('.js')) continue;
|
|
10163
|
+
const jsSource = getAssetSource(compilation, chunkFileName);
|
|
10164
|
+
if (!jsSource) continue;
|
|
10165
|
+
const matchedStrings = jsSource.match(EMITTED_ASSET_REF_PATTERN) || [];
|
|
10166
|
+
for(let m = 0; m < matchedStrings.length; m++)addFileIfRelevant(matchedStrings[m]);
|
|
10167
|
+
}
|
|
10168
|
+
});
|
|
10169
|
+
const logicalJsAssetName = `${entryName}.js`;
|
|
10170
|
+
const logicalJsAssetSource = getAssetSource(compilation, logicalJsAssetName);
|
|
10171
|
+
if (logicalJsAssetSource) {
|
|
10172
|
+
const matchedStrings = logicalJsAssetSource.match(EMITTED_ASSET_REF_PATTERN) || [];
|
|
10173
|
+
for(let n = 0; n < matchedStrings.length; n++)addFileIfRelevant(matchedStrings[n]);
|
|
10174
|
+
}
|
|
10175
|
+
entryImports[entryName] = Array.from(collectedFilesSet);
|
|
10176
|
+
});
|
|
10177
|
+
const entryImportsEntries = Object.entries(entryImports);
|
|
10178
|
+
for(let i = 0; i < entryImportsEntries.length; i++){
|
|
10179
|
+
const name = entryImportsEntries[i][0];
|
|
10180
|
+
const files = entryImportsEntries[i][1];
|
|
10181
|
+
const normalizedFiles = [];
|
|
10182
|
+
for(let j = 0; j < files.length; j++)normalizedFiles.push(unixify(files[j]));
|
|
10183
|
+
entryImports[name] = normalizedFiles;
|
|
10184
|
+
}
|
|
10185
|
+
return entryImports;
|
|
10186
|
+
}
|
|
9936
10187
|
function cleanMatches(matches) {
|
|
9937
10188
|
return matches.map((match)=>{
|
|
9938
10189
|
try {
|
|
@@ -10072,6 +10323,9 @@ function resolve_war_findSourceSibling(absOutputPath) {
|
|
|
10072
10323
|
function isFirefox(browser) {
|
|
10073
10324
|
return !!browser && isGeckoBasedBrowser(browser.toLowerCase());
|
|
10074
10325
|
}
|
|
10326
|
+
function isWebkit(browser) {
|
|
10327
|
+
return !!browser && isWebkitBasedBrowser(browser.toLowerCase());
|
|
10328
|
+
}
|
|
10075
10329
|
function isValidChromeMatchPattern(pattern) {
|
|
10076
10330
|
if ('<all_urls>' === pattern) return true;
|
|
10077
10331
|
if (/[?#]/.test(pattern)) return false;
|
|
@@ -10085,7 +10339,7 @@ function isValidChromeMatchPattern(pattern) {
|
|
|
10085
10339
|
}
|
|
10086
10340
|
}
|
|
10087
10341
|
function validateMatchesOrReport(compilation, matches, browser) {
|
|
10088
|
-
if (!matches || isFirefox(browser)) return;
|
|
10342
|
+
if (!matches || isFirefox(browser) || isWebkit(browser)) return;
|
|
10089
10343
|
compilation.errors ||= [];
|
|
10090
10344
|
for (const m of matches)if (!isValidChromeMatchPattern(m)) {
|
|
10091
10345
|
const msg = warInvalidMatchPattern(m);
|
|
@@ -10227,7 +10481,7 @@ function resolveUserDeclaredWAR(compilation, manifestPath, manifest, browser) {
|
|
|
10227
10481
|
v3
|
|
10228
10482
|
};
|
|
10229
10483
|
}
|
|
10230
|
-
function
|
|
10484
|
+
function generate_manifest_getAssetSource(compilation, filename) {
|
|
10231
10485
|
const byGet = 'function' == typeof compilation.getAsset ? compilation.getAsset(filename) : void 0;
|
|
10232
10486
|
const byAssets = !byGet && compilation.assets ? compilation.assets[filename] : void 0;
|
|
10233
10487
|
const asset = byGet || byAssets;
|
|
@@ -10318,10 +10572,9 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
|
|
|
10318
10572
|
const cacheKey = assetForCache && 'object' == typeof assetForCache.source ? assetForCache.source : void 0;
|
|
10319
10573
|
let filtered = cacheKey ? assetScanCache.get(cacheKey) : void 0;
|
|
10320
10574
|
if (!filtered) {
|
|
10321
|
-
const source =
|
|
10575
|
+
const source = generate_manifest_getAssetSource(compilation, jsFile);
|
|
10322
10576
|
if (!source) continue;
|
|
10323
|
-
const
|
|
10324
|
-
const found = source.match(re) || [];
|
|
10577
|
+
const found = source.match(EMITTED_ASSET_REF_PATTERN) || [];
|
|
10325
10578
|
filtered = Array.from(new Set(found.filter((r)=>!r.endsWith('.js') && !r.endsWith('.map')))).sort();
|
|
10326
10579
|
if (cacheKey) assetScanCache.set(cacheKey, filtered);
|
|
10327
10580
|
}
|
|
@@ -10484,6 +10737,15 @@ function collectRequiredManifestFiles(manifest) {
|
|
|
10484
10737
|
const backgroundScripts = background?.scripts;
|
|
10485
10738
|
if (Array.isArray(backgroundScripts)) for (const script of backgroundScripts)addFile(script);
|
|
10486
10739
|
addFile(manifestObj?.side_panel?.default_path);
|
|
10740
|
+
addFile(manifestObj?.action?.default_popup);
|
|
10741
|
+
addFile(manifestObj?.browser_action?.default_popup);
|
|
10742
|
+
addFile(manifestObj?.page_action?.default_popup);
|
|
10743
|
+
addFile(manifestObj?.options_ui?.page);
|
|
10744
|
+
addFile(manifestObj?.options_page);
|
|
10745
|
+
addFile(manifestObj?.devtools_page);
|
|
10746
|
+
addFile(manifestObj?.chrome_url_overrides?.newtab);
|
|
10747
|
+
addFile(manifestObj?.chrome_url_overrides?.history);
|
|
10748
|
+
addFile(manifestObj?.chrome_url_overrides?.bookmarks);
|
|
10487
10749
|
const contentScripts = manifestObj?.content_scripts;
|
|
10488
10750
|
if (Array.isArray(contentScripts)) for (const contentScript of contentScripts){
|
|
10489
10751
|
const js = contentScript?.js;
|
|
@@ -10763,6 +11025,78 @@ function patchChromiumBackground(manifest, browser) {
|
|
|
10763
11025
|
}
|
|
10764
11026
|
};
|
|
10765
11027
|
}
|
|
11028
|
+
const isChannel = (entry)=>'number' == typeof entry && Number.isInteger(entry) && entry >= 0 && entry <= 255;
|
|
11029
|
+
const isFiniteNumber = (entry)=>'number' == typeof entry && Number.isFinite(entry);
|
|
11030
|
+
function parseHexThemeColor(value) {
|
|
11031
|
+
if ('string' != typeof value) return;
|
|
11032
|
+
const match = /^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(value.trim());
|
|
11033
|
+
if (!match) return;
|
|
11034
|
+
const hex = match[1];
|
|
11035
|
+
const digits = hex.length >= 6 ? hex.match(/../g) : hex.split('').map((digit)=>digit + digit);
|
|
11036
|
+
const bytes = digits.map((pair)=>parseInt(pair, 16));
|
|
11037
|
+
if (3 === bytes.length) return bytes;
|
|
11038
|
+
return [
|
|
11039
|
+
...bytes.slice(0, 3),
|
|
11040
|
+
Math.round(bytes[3] / 255 * 1000) / 1000
|
|
11041
|
+
];
|
|
11042
|
+
}
|
|
11043
|
+
function colorValueDetail(value) {
|
|
11044
|
+
if (parseHexThemeColor(value)) return;
|
|
11045
|
+
if (!Array.isArray(value) || 3 !== value.length && 4 !== value.length) return 'Chrome only accepts an [R, G, B] or [R, G, B, A] array here.';
|
|
11046
|
+
for (const entry of value.slice(0, 3))if (!isChannel(entry)) return 'Chrome only accepts integer color channels from 0 to 255 here.';
|
|
11047
|
+
if (4 === value.length && !isFiniteNumber(value[3])) return 'Chrome only accepts a numeric alpha channel here.';
|
|
11048
|
+
}
|
|
11049
|
+
function tintValueDetail(value) {
|
|
11050
|
+
if (!Array.isArray(value) || 3 !== value.length || !value.every(isFiniteNumber)) return 'Chrome only accepts a [hue, saturation, lightness] array of 3 numbers here.';
|
|
11051
|
+
}
|
|
11052
|
+
function collectThemeValueIssues(manifest) {
|
|
11053
|
+
const issues = [];
|
|
11054
|
+
const theme = manifest?.theme;
|
|
11055
|
+
if (!theme || 'object' != typeof theme) return issues;
|
|
11056
|
+
const groups = [
|
|
11057
|
+
[
|
|
11058
|
+
'colors',
|
|
11059
|
+
theme.colors,
|
|
11060
|
+
colorValueDetail
|
|
11061
|
+
],
|
|
11062
|
+
[
|
|
11063
|
+
'tints',
|
|
11064
|
+
theme.tints,
|
|
11065
|
+
tintValueDetail
|
|
11066
|
+
]
|
|
11067
|
+
];
|
|
11068
|
+
for (const [group, container, detailFor] of groups)if (!(!container || 'object' != typeof container || Array.isArray(container))) for (const [key, value] of Object.entries(container)){
|
|
11069
|
+
const detail = detailFor(value);
|
|
11070
|
+
if (detail) issues.push({
|
|
11071
|
+
field: `theme.${group}.${key}`,
|
|
11072
|
+
detail,
|
|
11073
|
+
value: JSON.stringify(value)
|
|
11074
|
+
});
|
|
11075
|
+
}
|
|
11076
|
+
return issues;
|
|
11077
|
+
}
|
|
11078
|
+
function patchChromiumThemeColors(manifest, browser) {
|
|
11079
|
+
if (!isChromiumBasedBrowser(String(browser))) return manifest;
|
|
11080
|
+
const theme = manifest.theme;
|
|
11081
|
+
if (!theme || 'object' != typeof theme || Array.isArray(theme)) return manifest;
|
|
11082
|
+
const colors = theme.colors;
|
|
11083
|
+
if (!colors || 'object' != typeof colors || Array.isArray(colors)) return manifest;
|
|
11084
|
+
let converted = false;
|
|
11085
|
+
const patchedColors = {};
|
|
11086
|
+
for (const [key, value] of Object.entries(colors)){
|
|
11087
|
+
const rgb = parseHexThemeColor(value);
|
|
11088
|
+
patchedColors[key] = rgb ?? value;
|
|
11089
|
+
if (rgb) converted = true;
|
|
11090
|
+
}
|
|
11091
|
+
if (!converted) return manifest;
|
|
11092
|
+
return {
|
|
11093
|
+
...manifest,
|
|
11094
|
+
theme: {
|
|
11095
|
+
...theme,
|
|
11096
|
+
colors: patchedColors
|
|
11097
|
+
}
|
|
11098
|
+
};
|
|
11099
|
+
}
|
|
10766
11100
|
function patchDevContentScriptManifestPaths(compilation, manifest) {
|
|
10767
11101
|
if ('development' !== compilation.options.mode) return manifest;
|
|
10768
11102
|
const cs = manifest.content_scripts;
|
|
@@ -10881,6 +11215,7 @@ class UpdateManifest {
|
|
|
10881
11215
|
let patchedManifest = buildCanonicalManifest(this.manifestPath, manifest, this.browser);
|
|
10882
11216
|
patchedManifest = patchGeckoBackground(patchedManifest, this.browser);
|
|
10883
11217
|
patchedManifest = patchChromiumBackground(patchedManifest, this.browser);
|
|
11218
|
+
patchedManifest = patchChromiumThemeColors(patchedManifest, this.browser);
|
|
10884
11219
|
const overrides = getManifestOverrides(this.manifestPath, manifest);
|
|
10885
11220
|
if ('development' === compiler.options.mode) {
|
|
10886
11221
|
if (patchedManifest.content_scripts) patchedManifest.content_scripts = this.applyDevOverrides(patchedManifest);
|
|
@@ -10922,42 +11257,6 @@ class UpdateManifest {
|
|
|
10922
11257
|
});
|
|
10923
11258
|
}
|
|
10924
11259
|
}
|
|
10925
|
-
const isChannel = (entry)=>'number' == typeof entry && Number.isInteger(entry) && entry >= 0 && entry <= 255;
|
|
10926
|
-
const isFiniteNumber = (entry)=>'number' == typeof entry && Number.isFinite(entry);
|
|
10927
|
-
function colorValueDetail(value) {
|
|
10928
|
-
if (!Array.isArray(value) || 3 !== value.length && 4 !== value.length) return 'Chrome only accepts an [R, G, B] or [R, G, B, A] array here.';
|
|
10929
|
-
for (const entry of value.slice(0, 3))if (!isChannel(entry)) return 'Chrome only accepts integer color channels from 0 to 255 here.';
|
|
10930
|
-
if (4 === value.length && !isFiniteNumber(value[3])) return 'Chrome only accepts a numeric alpha channel here.';
|
|
10931
|
-
}
|
|
10932
|
-
function tintValueDetail(value) {
|
|
10933
|
-
if (!Array.isArray(value) || 3 !== value.length || !value.every(isFiniteNumber)) return 'Chrome only accepts a [hue, saturation, lightness] array of 3 numbers here.';
|
|
10934
|
-
}
|
|
10935
|
-
function collectThemeValueIssues(manifest) {
|
|
10936
|
-
const issues = [];
|
|
10937
|
-
const theme = manifest?.theme;
|
|
10938
|
-
if (!theme || 'object' != typeof theme) return issues;
|
|
10939
|
-
const groups = [
|
|
10940
|
-
[
|
|
10941
|
-
'colors',
|
|
10942
|
-
theme.colors,
|
|
10943
|
-
colorValueDetail
|
|
10944
|
-
],
|
|
10945
|
-
[
|
|
10946
|
-
'tints',
|
|
10947
|
-
theme.tints,
|
|
10948
|
-
tintValueDetail
|
|
10949
|
-
]
|
|
10950
|
-
];
|
|
10951
|
-
for (const [group, container, detailFor] of groups)if (!(!container || 'object' != typeof container || Array.isArray(container))) for (const [key, value] of Object.entries(container)){
|
|
10952
|
-
const detail = detailFor(value);
|
|
10953
|
-
if (detail) issues.push({
|
|
10954
|
-
field: `theme.${group}.${key}`,
|
|
10955
|
-
detail,
|
|
10956
|
-
value: JSON.stringify(value)
|
|
10957
|
-
});
|
|
10958
|
-
}
|
|
10959
|
-
return issues;
|
|
10960
|
-
}
|
|
10961
11260
|
class ValidateThemeValues {
|
|
10962
11261
|
static name = 'manifest:validate-theme-values';
|
|
10963
11262
|
manifestPath;
|
|
@@ -10967,7 +11266,9 @@ class ValidateThemeValues {
|
|
|
10967
11266
|
this.browser = options.browser || 'chrome';
|
|
10968
11267
|
}
|
|
10969
11268
|
apply(compiler) {
|
|
10970
|
-
|
|
11269
|
+
const browserName = String(this.browser);
|
|
11270
|
+
const webkitTarget = isWebkitBasedBrowser(browserName);
|
|
11271
|
+
if (!isChromiumBasedBrowser(browserName) && !webkitTarget) return;
|
|
10971
11272
|
compiler.hooks.thisCompilation.tap(ValidateThemeValues.name, (compilation)=>{
|
|
10972
11273
|
compilation.hooks.processAssets.tap({
|
|
10973
11274
|
name: ValidateThemeValues.name,
|
|
@@ -10979,6 +11280,10 @@ class ValidateThemeValues {
|
|
|
10979
11280
|
} catch {
|
|
10980
11281
|
return;
|
|
10981
11282
|
}
|
|
11283
|
+
if (webkitTarget) {
|
|
11284
|
+
if (manifest.theme) reportToCompilation(compilation, compiler, themeNotSupportedByBrowser(browserName), 'warning', 'manifest.json');
|
|
11285
|
+
return;
|
|
11286
|
+
}
|
|
10982
11287
|
for (const issue of collectThemeValueIssues(manifest))reportToCompilation(compilation, compiler, invalidThemeValue(issue.field, issue.detail, issue.value), 'error', 'manifest.json');
|
|
10983
11288
|
});
|
|
10984
11289
|
});
|
|
@@ -11436,100 +11741,6 @@ class ScriptsPlugin {
|
|
|
11436
11741
|
new ValidateContentScriptSyntax().apply(compiler);
|
|
11437
11742
|
}
|
|
11438
11743
|
}
|
|
11439
|
-
function forEachStringKey(objectOrMap, callback) {
|
|
11440
|
-
if (!objectOrMap) return;
|
|
11441
|
-
if (objectOrMap instanceof Map) {
|
|
11442
|
-
const keys = objectOrMap.keys();
|
|
11443
|
-
for (const key of keys)callback(String(key));
|
|
11444
|
-
} else if ('object' == typeof objectOrMap) {
|
|
11445
|
-
const objectKeys = Object.keys(objectOrMap);
|
|
11446
|
-
for (const key of objectKeys)callback(key);
|
|
11447
|
-
}
|
|
11448
|
-
}
|
|
11449
|
-
function collect_entry_imports_getAssetSource(compilation, filename) {
|
|
11450
|
-
let assetGetFunction;
|
|
11451
|
-
if ('function' == typeof compilation.getAsset) assetGetFunction = compilation.getAsset(filename);
|
|
11452
|
-
let assetViaAssets;
|
|
11453
|
-
if (!assetGetFunction && compilation.assets) assetViaAssets = compilation.assets[filename];
|
|
11454
|
-
const asset = assetGetFunction || assetViaAssets;
|
|
11455
|
-
if (!asset) return '';
|
|
11456
|
-
let src;
|
|
11457
|
-
src = 'function' == typeof asset.source ? asset.source() : asset.source?.source ? asset.source.source() : asset.source;
|
|
11458
|
-
if ('string' == typeof src) return src;
|
|
11459
|
-
return '';
|
|
11460
|
-
}
|
|
11461
|
-
function collectContentScriptEntryImports(compilation, includeList) {
|
|
11462
|
-
const entryImports = {};
|
|
11463
|
-
const contentEntryNames = new Set(Object.keys(includeList || {}).filter((k)=>k.startsWith("content_scripts")));
|
|
11464
|
-
const chunkGraph = compilation.chunkGraph;
|
|
11465
|
-
compilation.entrypoints.forEach((_entry, entryName)=>{
|
|
11466
|
-
if (String(entryName).startsWith("content_scripts/")) contentEntryNames.add(entryName);
|
|
11467
|
-
});
|
|
11468
|
-
compilation.entrypoints.forEach((entry, entryName)=>{
|
|
11469
|
-
if (!contentEntryNames.has(entryName)) return;
|
|
11470
|
-
const collectedFilesSet = new Set();
|
|
11471
|
-
function addFileIfRelevant(file) {
|
|
11472
|
-
if (null == file) return;
|
|
11473
|
-
const fileNameStr = String(file);
|
|
11474
|
-
const isJavaScript = fileNameStr.endsWith('.js');
|
|
11475
|
-
const isSourceMap = fileNameStr.endsWith('.map');
|
|
11476
|
-
if (isJavaScript || isSourceMap) return;
|
|
11477
|
-
collectedFilesSet.add(fileNameStr);
|
|
11478
|
-
}
|
|
11479
|
-
entry.chunks.forEach((chunk)=>{
|
|
11480
|
-
const currentChunk = chunk;
|
|
11481
|
-
const chunkFilesArray = Array.isArray(currentChunk.files) ? currentChunk.files : [];
|
|
11482
|
-
for(let i = 0; i < chunkFilesArray.length; i++)addFileIfRelevant(chunkFilesArray[i]);
|
|
11483
|
-
let chunkAuxFilesArray = [];
|
|
11484
|
-
if (Array.isArray(currentChunk.auxiliaryFiles)) chunkAuxFilesArray = currentChunk.auxiliaryFiles;
|
|
11485
|
-
for(let i = 0; i < chunkAuxFilesArray.length; i++)addFileIfRelevant(chunkAuxFilesArray[i]);
|
|
11486
|
-
const modulesArray = Array.from(chunkGraph.getChunkModulesIterable(chunk));
|
|
11487
|
-
for(let j = 0; j < modulesArray.length; j++){
|
|
11488
|
-
const moduleObj = modulesArray[j];
|
|
11489
|
-
const moduleChunksArray = Array.from(chunkGraph.getModuleChunks(moduleObj));
|
|
11490
|
-
for(let k = 0; k < moduleChunksArray.length; k++){
|
|
11491
|
-
const mk = moduleChunksArray[k];
|
|
11492
|
-
const mkAuxFilesArr = Array.isArray(mk.auxiliaryFiles) ? mk.auxiliaryFiles : [];
|
|
11493
|
-
for(let l = 0; l < mkAuxFilesArr.length; l++)addFileIfRelevant(mkAuxFilesArr[l]);
|
|
11494
|
-
}
|
|
11495
|
-
const moduleWithBuildInfo = moduleObj;
|
|
11496
|
-
const buildInfo = moduleWithBuildInfo.buildInfo;
|
|
11497
|
-
forEachStringKey(buildInfo?.assets, (key)=>{
|
|
11498
|
-
addFileIfRelevant(key);
|
|
11499
|
-
});
|
|
11500
|
-
forEachStringKey(buildInfo?.assetsInfo, (key)=>{
|
|
11501
|
-
addFileIfRelevant(key);
|
|
11502
|
-
});
|
|
11503
|
-
}
|
|
11504
|
-
for(let i = 0; i < chunkFilesArray.length; i++){
|
|
11505
|
-
const chunkFileName = chunkFilesArray[i];
|
|
11506
|
-
if (!String(chunkFileName).endsWith('.js')) continue;
|
|
11507
|
-
const jsSource = collect_entry_imports_getAssetSource(compilation, chunkFileName);
|
|
11508
|
-
if (!jsSource) continue;
|
|
11509
|
-
const assetPattern = /assets\/[A-Za-z0-9._-]+/g;
|
|
11510
|
-
const matchedStrings = jsSource.match(assetPattern) || [];
|
|
11511
|
-
for(let m = 0; m < matchedStrings.length; m++)addFileIfRelevant(matchedStrings[m]);
|
|
11512
|
-
}
|
|
11513
|
-
});
|
|
11514
|
-
const logicalJsAssetName = `${entryName}.js`;
|
|
11515
|
-
const logicalJsAssetSource = collect_entry_imports_getAssetSource(compilation, logicalJsAssetName);
|
|
11516
|
-
if (logicalJsAssetSource) {
|
|
11517
|
-
const assetPattern = /assets\/[A-Za-z0-9._-]+/g;
|
|
11518
|
-
const matchedStrings = logicalJsAssetSource.match(assetPattern) || [];
|
|
11519
|
-
for(let n = 0; n < matchedStrings.length; n++)addFileIfRelevant(matchedStrings[n]);
|
|
11520
|
-
}
|
|
11521
|
-
entryImports[entryName] = Array.from(collectedFilesSet);
|
|
11522
|
-
});
|
|
11523
|
-
const entryImportsEntries = Object.entries(entryImports);
|
|
11524
|
-
for(let i = 0; i < entryImportsEntries.length; i++){
|
|
11525
|
-
const name = entryImportsEntries[i][0];
|
|
11526
|
-
const files = entryImportsEntries[i][1];
|
|
11527
|
-
const normalizedFiles = [];
|
|
11528
|
-
for(let j = 0; j < files.length; j++)normalizedFiles.push(unixify(files[j]));
|
|
11529
|
-
entryImports[name] = normalizedFiles;
|
|
11530
|
-
}
|
|
11531
|
-
return entryImports;
|
|
11532
|
-
}
|
|
11533
11744
|
class CollectContentEntryImports {
|
|
11534
11745
|
includeList;
|
|
11535
11746
|
constructor(options){
|
|
@@ -11572,10 +11783,13 @@ class WebResourcesPlugin {
|
|
|
11572
11783
|
function isCriticalJsonFeatureKey(key) {
|
|
11573
11784
|
return key.startsWith('declarative_net_request') || 'storage.managed_schema' === key;
|
|
11574
11785
|
}
|
|
11786
|
+
function toComparablePath(value) {
|
|
11787
|
+
return 'string' == typeof value ? value : JSON.stringify(value);
|
|
11788
|
+
}
|
|
11575
11789
|
function flattenValues(map) {
|
|
11576
11790
|
const paths = [];
|
|
11577
|
-
for (const val of Object.values(map || {}))if (Array.isArray(val)) paths.push(...val.filter(Boolean));
|
|
11578
|
-
else if (val) paths.push(val);
|
|
11791
|
+
for (const val of Object.values(map || {}))if (Array.isArray(val)) paths.push(...val.filter(Boolean).map(toComparablePath));
|
|
11792
|
+
else if (val) paths.push(toComparablePath(val));
|
|
11579
11793
|
return paths;
|
|
11580
11794
|
}
|
|
11581
11795
|
function diffArray(prev, next) {
|
|
@@ -11628,7 +11842,7 @@ class ManifestFieldsChangeDetector {
|
|
|
11628
11842
|
else if (val) scripts.push(val);
|
|
11629
11843
|
const html = fields.html || {};
|
|
11630
11844
|
const iconsRaw = fields.icons;
|
|
11631
|
-
const icons = iconsRaw ? Array.isArray(iconsRaw) ? iconsRaw : flattenValues(iconsRaw) : [];
|
|
11845
|
+
const icons = iconsRaw ? Array.isArray(iconsRaw) ? iconsRaw.filter(Boolean).map(toComparablePath) : flattenValues(iconsRaw) : [];
|
|
11632
11846
|
const jsonMap = fields.json || {};
|
|
11633
11847
|
const json = [];
|
|
11634
11848
|
for (const [key, val] of Object.entries(jsonMap))if (isCriticalJsonFeatureKey(key)) {
|
|
@@ -11800,6 +12014,7 @@ function webpackConfig(projectStructure, devOptions) {
|
|
|
11800
12014
|
}
|
|
11801
12015
|
const manifest = filterKeysForThisBrowser(rawManifest, devOptions.browser);
|
|
11802
12016
|
const primaryExtensionOutputDir = asAbsolute(__rspack_external_node_path_c5b9b54f.isAbsolute(devOptions.output.path) ? devOptions.output.path : __rspack_external_node_path_c5b9b54f.resolve(packageJsonDir, devOptions.output.path));
|
|
12017
|
+
const publishedExtensionOutputDir = devOptions.output.finalPath ? asAbsolute(__rspack_external_node_path_c5b9b54f.isAbsolute(devOptions.output.finalPath) ? devOptions.output.finalPath : __rspack_external_node_path_c5b9b54f.resolve(packageJsonDir, devOptions.output.finalPath)) : primaryExtensionOutputDir;
|
|
11803
12018
|
const companionUnpackedExtensionDirs = resolveCompanionExtensionDirs({
|
|
11804
12019
|
projectRoot: packageJsonDir,
|
|
11805
12020
|
config: devOptions.extensions
|
|
@@ -11926,7 +12141,7 @@ function webpackConfig(projectStructure, devOptions) {
|
|
|
11926
12141
|
browser: devOptions.browser,
|
|
11927
12142
|
mode: devOptions.mode,
|
|
11928
12143
|
command: devOptions.metadataCommand,
|
|
11929
|
-
outputPath:
|
|
12144
|
+
outputPath: publishedExtensionOutputDir,
|
|
11930
12145
|
manifestPath,
|
|
11931
12146
|
port: devOptions.port,
|
|
11932
12147
|
host: process.env.EXTENSION_DEV_SERVER_CONNECTABLE_HOST || devOptions.host,
|