extension-develop 4.1.19 → 4.1.21
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/672~0.mjs +24 -1
- package/dist/747~0.mjs +4 -2
- package/dist/832~0.mjs +26 -6
- package/dist/840~0.mjs +507 -26
- package/dist/950~0.mjs +18 -26
- package/dist/dev-server/control-bridge/actions-file.d.ts +0 -1
- package/dist/dev-server/control-bridge/broker.d.ts +6 -4
- package/dist/dev-server/control-bridge/contracts.d.ts +1 -1
- package/dist/dev-server/control-bridge/logs-file.d.ts +0 -1
- package/dist/dev-server/control-bridge/producer-runtime.d.ts +1 -2
- package/dist/dev-server~0.mjs +19 -5
- package/dist/extension-js-devtools/edge/manifest.json +0 -1
- package/dist/lib/addon-lint.d.ts +4 -1
- package/dist/lib/chunk-dependency-provenance.d.ts +14 -0
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/ensure-develop-artifacts.d.ts +0 -7
- package/dist/lib/has-dependency.d.ts +0 -5
- package/dist/lib/manifest-utils.d.ts +2 -0
- package/dist/lib/merge-options.d.ts +0 -40
- package/dist/lib/messages.d.ts +4 -4
- package/dist/lib/package-manager.d.ts +2 -0
- package/dist/lib/project-manifest.d.ts +0 -1
- package/dist/lib/session-paths.d.ts +0 -22
- package/dist/plugin-browsers/index.d.ts +0 -7
- package/dist/plugin-browsers/safari-dev-plugin.d.ts +4 -0
- package/dist/plugin-compatibility/feature-polyfill.d.ts +0 -4
- package/dist/plugin-compilation/env.d.ts +2 -5
- package/dist/plugin-css/css-lib/dead-url-refs.d.ts +0 -6
- package/dist/plugin-css/css-lib/inline-content-script-css.d.ts +0 -15
- package/dist/plugin-css/css-lib/resolve-css-asset.d.ts +0 -8
- package/dist/plugin-js-frameworks/js-frameworks-lib/messages.d.ts +1 -0
- package/dist/plugin-js-frameworks/js-tools/solid.d.ts +3 -0
- package/dist/plugin-js-frameworks/js-tools/typescript.d.ts +16 -0
- package/dist/plugin-perf-budgets/categorize.d.ts +2 -1
- package/dist/plugin-perf-budgets/index.d.ts +1 -22
- package/dist/plugin-playwright/index.d.ts +3 -2
- package/dist/plugin-reload/index.d.ts +1 -1
- package/dist/plugin-reload/reload-dispatch.d.ts +6 -3
- package/dist/plugin-reload/steps/setup-chunk-loading-target.d.ts +0 -13
- package/dist/plugin-special-folders/index.d.ts +0 -9
- package/dist/plugin-web-extension/feature-html/html-lib/utils.d.ts +0 -1
- package/dist/plugin-web-extension/feature-html/index.d.ts +0 -27
- package/dist/plugin-web-extension/feature-icons/index.d.ts +0 -12
- package/dist/plugin-web-extension/feature-json/index.d.ts +0 -9
- package/dist/plugin-web-extension/feature-locales/index.d.ts +0 -4
- package/dist/plugin-web-extension/feature-manifest/index.d.ts +0 -10
- package/dist/plugin-web-extension/feature-manifest/manifest-lib/filter-key-edge.d.ts +5 -0
- package/dist/plugin-web-extension/feature-manifest/manifest-lib/filter-keys-safari.d.ts +11 -0
- package/dist/plugin-web-extension/feature-manifest/manifest-lib/gecko-data-collection.d.ts +0 -12
- package/dist/plugin-web-extension/feature-manifest/manifest-lib/legacy-paths.d.ts +0 -13
- package/dist/plugin-web-extension/feature-manifest/manifest-lib/sanitize-fatal-shapes.d.ts +0 -36
- package/dist/plugin-web-extension/feature-manifest/messages.d.ts +20 -0
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/dev-injected-hosts.d.ts +0 -5
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/emitted-evidence.d.ts +22 -0
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/patch-background.d.ts +9 -0
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/patch-web-resources.d.ts +7 -16
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults.d.ts +6 -2
- package/dist/plugin-web-extension/feature-manifest/steps/patch-war.d.ts +0 -5
- package/dist/plugin-web-extension/feature-manifest/steps/patch-webkit-background.d.ts +2 -0
- package/dist/plugin-web-extension/feature-manifest/steps/update-manifest.d.ts +1 -0
- package/dist/plugin-web-extension/feature-manifest/steps/warn-gecko-unsupported-apis.d.ts +119 -26
- package/dist/plugin-web-extension/feature-scripts/index.d.ts +0 -10
- package/dist/plugin-web-extension/feature-scripts/messages.d.ts +5 -0
- package/dist/plugin-web-extension/feature-scripts/steps/native-geturl-import-loader.d.ts +0 -3
- package/dist/plugin-web-extension/feature-scripts/steps/warn-page-context-worker.d.ts +5 -0
- package/dist/plugin-web-extension/feature-web-resources/collect-entry-imports.d.ts +1 -0
- package/dist/plugin-web-extension/feature-web-resources/index.d.ts +0 -10
- package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/clean-matches.d.ts +0 -6
- package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/messages.d.ts +1 -0
- package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/unreachable-resources.d.ts +9 -0
- package/dist/plugin-web-extension/shared/discover-devtools-panels.d.ts +0 -6
- package/dist/plugin-web-extension/shared/paths.d.ts +0 -1
- package/dist/rspack-config.d.ts +1 -1
- package/dist/rspack-config~0.mjs +1074 -574
- package/package.json +1 -1
- package/runtime/process-shim.cjs +2 -0
package/dist/rspack-config~0.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
|
+
import core, { Compilation as core_Compilation, DefinePlugin, EntryPlugin, LightningCssMinimizerRspackPlugin, ProvidePlugin, SwcJsMinimizerRspackPlugin, WebpackError as core_WebpackError, experiments, javascript as core_javascript, library, rspack, sources as core_sources } from "@rspack/core";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import pintor from "pintor";
|
|
4
|
-
import core, { Compilation as core_Compilation, DefinePlugin, EntryPlugin, ProvidePlugin, WebpackError as core_WebpackError, javascript as core_javascript, library, rspack, sources as core_sources } from "@rspack/core";
|
|
5
5
|
import case_sensitive_paths_webpack_plugin from "case-sensitive-paths-webpack-plugin";
|
|
6
6
|
import { zipSync } from "fflate";
|
|
7
7
|
import ignore from "ignore";
|
|
@@ -14,12 +14,12 @@ import node_path from "node:path";
|
|
|
14
14
|
import { utils_isUrl, getBaseNode, parseHtml, manifestJsonOutputTarget, getExtname, getBaseHref, isResourceUnderDirs, getAssetsFromHtml, normalizeManifestOutputPath, manifestPageOutputTarget, canonicalizeDir, iconOutputPath, isFromIncludeList, htmlStaticAssetOutputName, isSpecialScheme, resolveStaticAttributeName, getHtmlPageDeclaredAssetPath, themeImageOutputPath, themeIconOutputPath, applyRewrittenStaticUrl, toResourceKey, cleanLeading, getFilePath, resolveAbsoluteFsPath, cleanAssetUrl, isHttpLike, resolveHtmlRefPath } from "./938~0.mjs";
|
|
15
15
|
import { prefix as messaging_prefix, isDebug } from "./852~0.mjs";
|
|
16
16
|
import { isChromiumBasedBrowser, CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, isWebkitBasedBrowser, isGeckoBasedBrowser } from "./331~0.mjs";
|
|
17
|
-
import { isUsingTypeScript, jsFrameworksIntegrationsEnabled, classifyEntrySurface, ensureTypeScriptConfig,
|
|
17
|
+
import { maybeUsePreact, isUsingTypeScript, jsFrameworksIntegrationsEnabled, maybeUseReact, isUsingVue, classifyEntrySurface, ensureTypeScriptConfig, resolveDevelopInstallRoot, loadLoaderOptions, getUserTypeScriptConfigFile, isUsingIntegration as messages_isUsingIntegration, maybeUseVue, maybeUseSolid, jsFrameworksHmrSummary, humanLine, ensureOptionalContractPackageResolved, jsFrameworksConfigsDetected, recordZipArtifact, hasDependency, resolveDevelopDistFile, isUsingJsxFramework, getJsxImportSource, swcParserForFile, isUsingReact, defaultSplitChunks } from "./840~0.mjs";
|
|
18
18
|
import { bundlerFatalError, bundlerRecompiling, browserRunnerDisabled, PlaywrightPlugin, publicFolderShadowed, resolveCompanionExtensionDirs, specialFoldersSetupSummary, noEntrypointsDetected, serverRestartRequiredFromSpecialFolderMessageOnly, specialFolderChangeDetected, spacerLine, messages_ready, getPreloadedEnvKeys, publicMustBeAtProjectRoot, computeExtensionsToLoad, getSpecialFoldersDataForCompiler } from "./832~0.mjs";
|
|
19
19
|
import { renderStatsBlocks, makeSanitizedConsole } from "./stats-handler~0.mjs";
|
|
20
20
|
import { stripBom, findNearestProjectManifestSync, PROJECT_MANIFEST_FILENAMES, parseJsonSafe, readProjectDependencies } from "./731~0.mjs";
|
|
21
21
|
import { EXTENSIONJS_CONTENT_SCRIPT_LAYER, getCanonicalContentScriptEntryName, parseCanonicalContentScriptAsset, CONTENT_SCRIPT_CSS_PROBE_MARKER_PREFIX, createContentScriptCssProbeMarkerPattern, getCanonicalContentScriptJsAssetName, getCanonicalContentScriptCssAssetName, isCanonicalContentScriptAsset } from "./640~0.mjs";
|
|
22
|
-
import { getURLDependencyMissing, findDroppedVendorKeys, isStaticThemeSource,
|
|
22
|
+
import { getURLDependencyMissing, findDroppedVendorKeys, isStaticThemeSource, workerStartedFromPageContext, importScriptsDependencyMissing, filterKeysForThisBrowser, findPrefixedManifestVersionKeys, injectedCompiledSourceLiteral, staticImportDependencyMissing, entrySplitAcrossInitialFiles, fetchedFileDependencyMissing, isStaticTheme, compiledSourceSpelling, injectedFileDependencyMissing, isValidManifestVersion, runtimeSetSurfaceDependencyMissing } from "./672~0.mjs";
|
|
23
23
|
import { packagingSourceFiles, debugBrowser, debugExtensionsToLoad, treeWithSourceFiles, debugOutputPath, manifestInvalidJson, getDirs, asAbsolute, treeWithDistFilesBrowser, packagingDistributionFiles, treeWithSourceAndDistFiles, toPosixPath as paths_toPosixPath, debugContextPath, noCompanionExtensionsResolved } from "./950~0.mjs";
|
|
24
24
|
import { cssMinifierDroppedRules, postCssConfigUnreadable, missingSassDependency, deadCssUrlRef, postCssPluginNotResolved, postCssConfigPluginsShape, cssIntegrationsEnabled, cssConfigsDetected, isUsingIntegration } from "./524~0.mjs";
|
|
25
25
|
import { minifierDroppedTokens, restoreVerbatimCssAssets } from "./88~0.mjs";
|
|
@@ -33,8 +33,6 @@ import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
|
33
33
|
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
34
34
|
import * as __rspack_external_dotenv from "dotenv";
|
|
35
35
|
import * as __rspack_external_parse5_utilities_4a00fdd6 from "parse5-utilities";
|
|
36
|
-
import * as __rspack_external_fs from "fs";
|
|
37
|
-
import * as __rspack_external_path from "path";
|
|
38
36
|
import * as __rspack_external_node_crypto_2e7c4b46 from "node:crypto";
|
|
39
37
|
function normalizePath(filePath) {
|
|
40
38
|
return filePath.replace(/\\/g, '/');
|
|
@@ -707,7 +705,7 @@ function optionsPage(manifest, manifestPath) {
|
|
|
707
705
|
})()
|
|
708
706
|
};
|
|
709
707
|
}
|
|
710
|
-
function
|
|
708
|
+
function options_ui_optionsUi(manifest, manifestPath) {
|
|
711
709
|
return manifest.options_ui && {
|
|
712
710
|
options_ui: {
|
|
713
711
|
...manifest.options_ui,
|
|
@@ -806,7 +804,7 @@ function manifestCommon(manifest, manifestPath, projectPath) {
|
|
|
806
804
|
...commands_commands(manifest),
|
|
807
805
|
...permissions_permissions(manifest),
|
|
808
806
|
...optionsPage(manifest, manifestPath),
|
|
809
|
-
...
|
|
807
|
+
...options_ui_optionsUi(manifest, manifestPath),
|
|
810
808
|
...sandbox(manifest, manifestPath),
|
|
811
809
|
...storage(manifest, manifestPath, projectPath),
|
|
812
810
|
...theme_theme(manifest, manifestPath),
|
|
@@ -1119,6 +1117,348 @@ function getManifestOverrides(manifestPath, manifest, projectPath) {
|
|
|
1119
1117
|
if (Object.keys(backgroundMerged).length) merged.background = backgroundMerged;
|
|
1120
1118
|
return JSON.stringify(dropMv2ObjectPolicy(dropMv2HostKeys(merged)), null, 2);
|
|
1121
1119
|
}
|
|
1120
|
+
function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
|
|
1121
|
+
const lines = [];
|
|
1122
|
+
lines.push("Entrypoint references changed.");
|
|
1123
|
+
if (fileRemoved) lines.push(`${pintor.gray('EXPECTED')} ${pintor.underline(fileRemoved)}`);
|
|
1124
|
+
if (fileAdded) lines.push(`${pintor.gray('GOT')} ${pintor.underline(fileAdded)}`);
|
|
1125
|
+
lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
|
|
1126
|
+
return lines.join('\n');
|
|
1127
|
+
}
|
|
1128
|
+
function legacyManifestPathWarning(field, legacyPath, modernPath) {
|
|
1129
|
+
const lines = [];
|
|
1130
|
+
lines.push(`${messaging_prefix('warn')} The ${pintor.blue(field)} field uses a deprecated scaffold path.`);
|
|
1131
|
+
lines.push(`${pintor.gray('PATH')} ${pintor.underline(legacyPath)}`);
|
|
1132
|
+
lines.push(`Point it at ${pintor.underline(modernPath)}, Extension.js already emits the page there.`);
|
|
1133
|
+
return lines.join('\n');
|
|
1134
|
+
}
|
|
1135
|
+
function fatalManifestShapeFixed(field, detail) {
|
|
1136
|
+
const lines = [];
|
|
1137
|
+
lines.push(`${messaging_prefix('warn')} Repaired the ${pintor.blue(field)} field, which Chrome refuses to load the extension over.`);
|
|
1138
|
+
lines.push(`${pintor.gray('REASON')} ${pintor.underline(detail)}`);
|
|
1139
|
+
lines.push(`Fix the field in your ${pintor.blue('manifest.json')} file.`);
|
|
1140
|
+
return lines.join('\n');
|
|
1141
|
+
}
|
|
1142
|
+
function invalidThemeValue(field, detail, value) {
|
|
1143
|
+
const lines = [];
|
|
1144
|
+
lines.push(`Check the ${pintor.yellow(field)} field in your ${pintor.yellow('manifest.json')} file.`);
|
|
1145
|
+
lines.push(detail);
|
|
1146
|
+
lines.push(`Chrome rejects the whole extension when this value is malformed.\nThe build stops here to protect you.`);
|
|
1147
|
+
lines.push('');
|
|
1148
|
+
lines.push(`${pintor.red('INVALID VALUE')} ${value}`);
|
|
1149
|
+
return lines.join('\n');
|
|
1150
|
+
}
|
|
1151
|
+
function themeNotSupportedByBrowser(browser) {
|
|
1152
|
+
const lines = [];
|
|
1153
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.blue(browser)} does not support the ${pintor.yellow('theme')} field.`);
|
|
1154
|
+
lines.push("The field ships unchanged in the manifest and Safari ignores it.");
|
|
1155
|
+
return lines.join('\n');
|
|
1156
|
+
}
|
|
1157
|
+
function missingGeckoDataCollectionPermissions() {
|
|
1158
|
+
const lines = [];
|
|
1159
|
+
lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.blue('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
|
|
1160
|
+
lines.push(`Declare ${pintor.blue('{"required": ["none"]}')} if this extension transmits no data.`);
|
|
1161
|
+
lines.push(`See ${pintor.underline('https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/')} for details.`);
|
|
1162
|
+
return lines.join('\n');
|
|
1163
|
+
}
|
|
1164
|
+
function manifestInvalidError(error) {
|
|
1165
|
+
const lines = [];
|
|
1166
|
+
lines.push(`Can't read your ${pintor.blue('manifest.json')} file.`);
|
|
1167
|
+
lines.push(`${pintor.gray('REASON')} ${pintor.underline(String(error))}`);
|
|
1168
|
+
lines.push("Update your manifest and try again.");
|
|
1169
|
+
return lines.join('\n');
|
|
1170
|
+
}
|
|
1171
|
+
function manifestIncludeSummary(browser, manifestPath) {
|
|
1172
|
+
return `${messaging_prefix('debug')} manifest include browser=${browser} path=${manifestPath}`;
|
|
1173
|
+
}
|
|
1174
|
+
function manifestEmitSuccess() {
|
|
1175
|
+
return `${messaging_prefix('debug')} manifest emitted=true schemaStripped=true`;
|
|
1176
|
+
}
|
|
1177
|
+
function manifestOverridesSummary(overrideKeys, devCssStubsAdded) {
|
|
1178
|
+
return `${messaging_prefix('debug')} manifest overrides keys=${String(overrideKeys)} devCssStubs=${String(devCssStubsAdded)}`;
|
|
1179
|
+
}
|
|
1180
|
+
function manifestDepsTracked(addedCount) {
|
|
1181
|
+
return `${messaging_prefix('debug')} manifest deps=${String(addedCount)}`;
|
|
1182
|
+
}
|
|
1183
|
+
function manifestLegacyWarningsSummary(count) {
|
|
1184
|
+
return `${messaging_prefix('debug')} manifest legacyWarnings=${String(count)}`;
|
|
1185
|
+
}
|
|
1186
|
+
function pageActionNotSupportedByBrowser(browser) {
|
|
1187
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} does not show the ${pintor.yellow('page_action')} address bar surface.\nThe field was dropped from the built manifest and its page was not emitted.`;
|
|
1188
|
+
}
|
|
1189
|
+
function pageActionDroppedForBrowserAction(browser) {
|
|
1190
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} refuses a Manifest V2 manifest that declares both ${pintor.yellow('browser_action')} and ${pintor.yellow('page_action')}.\nThe build kept ${pintor.yellow('browser_action')} and dropped ${pintor.yellow('page_action')} from the built manifest, so its page was not emitted. Remove one of the two keys, or scope page_action with the firefox: prefix.`;
|
|
1191
|
+
}
|
|
1192
|
+
function vendorPrefixedKeyDropped(key, familyKey, vendor, browser) {
|
|
1193
|
+
const vendorName = 'edge' === vendor ? 'Edge' : 'Chrome';
|
|
1194
|
+
return `${messaging_prefix('warn')} ${pintor.yellow(key)} now applies only to ${vendorName} builds, so the ${pintor.blue(browser)} build dropped it.\nRename it to ${pintor.yellow(familyKey)} to keep it on every Chromium-based browser. Leave it as is if it's meant for ${vendorName} only.`;
|
|
1195
|
+
}
|
|
1196
|
+
function prefixScope(prefix) {
|
|
1197
|
+
if ('chrome' === prefix) return 'Chrome';
|
|
1198
|
+
if ('edge' === prefix) return 'Edge';
|
|
1199
|
+
if ('chromium' === prefix) return 'Chromium-based';
|
|
1200
|
+
if ('firefox' === prefix || 'gecko' === prefix) return 'Firefox-based';
|
|
1201
|
+
if ('safari' === prefix || 'webkit' === prefix) return 'Safari';
|
|
1202
|
+
return prefix;
|
|
1203
|
+
}
|
|
1204
|
+
function manifestVersionLostForBrowser(browser, prefixedKeys, resolved) {
|
|
1205
|
+
const target = pintor.blue(browser);
|
|
1206
|
+
const field = pintor.yellow('manifest_version');
|
|
1207
|
+
const scoped = prefixedKeys.map((key)=>{
|
|
1208
|
+
const scope = prefixScope(key.substring(0, key.indexOf(':')));
|
|
1209
|
+
return `${pintor.yellow(key)} applies only to ${scope} builds`;
|
|
1210
|
+
});
|
|
1211
|
+
const lead = void 0 === resolved ? scoped.length ? `${scoped.join(', ')}, so the ${target} build has no ${field}.` : `The ${target} build has no ${field}.` : `The ${target} build resolved ${field} to ${pintor.yellow(JSON.stringify(resolved))}, and browsers load only 2 or 3.`;
|
|
1212
|
+
return `${messaging_prefix('error')} ${lead}\nNo browser loads a manifest without it, so the build was refused. Add a plain ${field}, or scope one to this browser: ${pintor.yellow('chromium:manifest_version')} for every Chromium-based browser, ${pintor.yellow('firefox:manifest_version')} for Firefox.`;
|
|
1213
|
+
}
|
|
1214
|
+
function edgeStoreKeyDropped(browser) {
|
|
1215
|
+
return `${messaging_prefix('warn')} Edge Add-ons refuses a package whose manifest carries ${pintor.yellow('key')}, so the ${pintor.blue(browser)} production build dropped it.\nPartner Center assigns the id that ${pintor.yellow('key')} pins everywhere else, so the field has no use in this package. Write it as ${pintor.yellow('chrome:key')} if it is meant for the Chrome Web Store build only.`;
|
|
1216
|
+
}
|
|
1217
|
+
function mv2SandboxPolicyDropped(browser) {
|
|
1218
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} reads a Manifest V2 ${pintor.yellow('content_security_policy')} as one string, so the ${pintor.yellow('sandbox')} slot has nowhere to go.\nThe build wrote the ${pintor.yellow('extension_pages')} policy as that string and dropped the sandbox policy from the built manifest. Scope the object form with the chromium: prefix, or declare a Manifest V3 build for this browser.`;
|
|
1219
|
+
}
|
|
1220
|
+
function geckoSidePanelUnsupported(file) {
|
|
1221
|
+
const lines = [];
|
|
1222
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.sidePanel, which is Chromium only.`);
|
|
1223
|
+
lines.push(`Firefox opens a sidebar through the ${pintor.yellow('sidebar_action')} manifest key on every manifest version, and addons-linter flags the call as UNSUPPORTED_API.`);
|
|
1224
|
+
lines.push(`Move the call behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')} so the Firefox bundle drops it.`);
|
|
1225
|
+
return lines.join('\n');
|
|
1226
|
+
}
|
|
1227
|
+
function safariUnsupportedApi(file, api, detail) {
|
|
1228
|
+
const lines = [];
|
|
1229
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} calls chrome.${api}, which Safari does not have.`);
|
|
1230
|
+
lines.push(detail);
|
|
1231
|
+
lines.push(`Move the call behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')}, or guard it with ${pintor.yellow(`chrome.${api}?.`)}.`);
|
|
1232
|
+
return lines.join('\n');
|
|
1233
|
+
}
|
|
1234
|
+
const safariBackgroundDies = "The call throws when the script runs, Safari drops the background, and nothing reports an error.";
|
|
1235
|
+
function safariSidePanelUnsupported(file) {
|
|
1236
|
+
return safariUnsupportedApi(file, 'sidePanel', "The call throws when the script runs. In a background service worker, Safari then never starts the worker, and nothing reports an error.");
|
|
1237
|
+
}
|
|
1238
|
+
function safariOffscreenUnsupported(file) {
|
|
1239
|
+
return safariUnsupportedApi(file, 'offscreen', `Safari has no offscreen documents, so that DOM work has no place to run. ${safariBackgroundDies}`);
|
|
1240
|
+
}
|
|
1241
|
+
function safariTabGroupsUnsupported(file) {
|
|
1242
|
+
return safariUnsupportedApi(file, 'tabGroups', `Safari has no tab groups, and its tabs carry no group id. ${safariBackgroundDies}`);
|
|
1243
|
+
}
|
|
1244
|
+
function safariManagementUnsupported(file) {
|
|
1245
|
+
return safariUnsupportedApi(file, 'management', `Safari exposes no management namespace at all, not even getSelf. ${safariBackgroundDies}`);
|
|
1246
|
+
}
|
|
1247
|
+
function safariUserScriptsUnsupported(file) {
|
|
1248
|
+
return safariUnsupportedApi(file, 'userScripts', `Safari has no userScripts namespace, and scripting.registerContentScripts is the closest it offers. ${safariBackgroundDies}`);
|
|
1249
|
+
}
|
|
1250
|
+
function safariIdentityUnsupported(file) {
|
|
1251
|
+
return safariUnsupportedApi(file, 'identity', `Safari has no identity namespace, and Apple points OAuth flows at a normal tab instead. ${safariBackgroundDies}`);
|
|
1252
|
+
}
|
|
1253
|
+
function safariNotificationsUnsupported(file) {
|
|
1254
|
+
return safariUnsupportedApi(file, 'notifications', `Safari has no notifications namespace, so a page has to raise the web Notification instead. ${safariBackgroundDies}`);
|
|
1255
|
+
}
|
|
1256
|
+
function safariOmniboxUnsupported(file) {
|
|
1257
|
+
return safariUnsupportedApi(file, 'omnibox', `Safari has no omnibox keyword API. ${safariBackgroundDies}`);
|
|
1258
|
+
}
|
|
1259
|
+
function safariBookmarksUnsupported(file) {
|
|
1260
|
+
return safariUnsupportedApi(file, 'bookmarks', `Safari does not expose bookmarks to extensions on any version. ${safariBackgroundDies}`);
|
|
1261
|
+
}
|
|
1262
|
+
function safariHistoryUnsupported(file) {
|
|
1263
|
+
return safariUnsupportedApi(file, 'history', `Safari does not expose browsing history to extensions on any version. ${safariBackgroundDies}`);
|
|
1264
|
+
}
|
|
1265
|
+
function safariDownloadsUnsupported(file) {
|
|
1266
|
+
return safariUnsupportedApi(file, 'downloads', `Safari has no downloads namespace. ${safariBackgroundDies}`);
|
|
1267
|
+
}
|
|
1268
|
+
function safariIdleUnsupported(file) {
|
|
1269
|
+
return safariUnsupportedApi(file, 'idle', `Safari has no idle namespace. ${safariBackgroundDies}`);
|
|
1270
|
+
}
|
|
1271
|
+
const safariMissingMemberDetails = {
|
|
1272
|
+
'action.getUserSettings': `Safari has no pinned-state query for the toolbar button, so there is no function to call. ${safariBackgroundDies}`,
|
|
1273
|
+
'action.getBadgeTextColor': `Safari draws the badge in its own colors and offers no badge text color call. ${safariBackgroundDies}`,
|
|
1274
|
+
'action.setBadgeTextColor': `Safari draws the badge in its own colors and offers no badge text color call. ${safariBackgroundDies}`,
|
|
1275
|
+
'action.onUserSettingsChanged': `Safari raises no event when the toolbar button settings change, so the listener attaches to nothing. ${safariBackgroundDies}`,
|
|
1276
|
+
'storage.managed': `Safari has no managed storage area, since it carries no enterprise policy channel for web extensions. ${safariBackgroundDies}`,
|
|
1277
|
+
'runtime.getContexts': `Safari keeps no inventory of extension contexts to hand back. ${safariBackgroundDies}`,
|
|
1278
|
+
'runtime.onSuspend': `Safari tears a background down without announcing it, so this lifecycle event does not exist. ${safariBackgroundDies}`,
|
|
1279
|
+
'runtime.onSuspendCanceled': `Safari tears a background down without announcing it, so this lifecycle event does not exist. ${safariBackgroundDies}`,
|
|
1280
|
+
'runtime.onUpdateAvailable': `Safari ships an extension inside its host app, so the browser raises no update event for it. ${safariBackgroundDies}`,
|
|
1281
|
+
'declarativeNetRequest.getAvailableStaticRuleCount': `Safari implements the blocking core of declarativeNetRequest and not its rule-budget queries. ${safariBackgroundDies}`,
|
|
1282
|
+
'declarativeNetRequest.getDisabledRuleIds': `Safari cannot disable individual static rules, so it has nothing to report here. ${safariBackgroundDies}`,
|
|
1283
|
+
'declarativeNetRequest.updateStaticRules': `Safari cannot toggle individual static rules, only whole rulesets through updateEnabledRulesets. ${safariBackgroundDies}`,
|
|
1284
|
+
'declarativeNetRequest.testMatchOutcome': `Safari has no rule-matching test harness, which is a Chrome debugging aid. ${safariBackgroundDies}`,
|
|
1285
|
+
'declarativeNetRequest.onRuleMatchedDebug': `Safari raises no rule-match debug event, which Chrome offers to unpacked extensions only. ${safariBackgroundDies}`,
|
|
1286
|
+
'tabs.group': `Safari has no tab groups at all, so there is no group to move a tab into. ${safariBackgroundDies}`,
|
|
1287
|
+
'tabs.ungroup': `Safari has no tab groups at all, so there is no group to take a tab out of. ${safariBackgroundDies}`,
|
|
1288
|
+
'webNavigation.onCreatedNavigationTarget': `Safari reports the main navigation events only, and this one is not among them. ${safariBackgroundDies}`,
|
|
1289
|
+
'webNavigation.onHistoryStateUpdated': `Safari reports the main navigation events only, so a History API navigation goes unannounced. ${safariBackgroundDies}`,
|
|
1290
|
+
'webNavigation.onReferenceFragmentUpdated': `Safari reports the main navigation events only, so a fragment change goes unannounced. ${safariBackgroundDies}`,
|
|
1291
|
+
'webNavigation.onTabReplaced': `Safari reports the main navigation events only, and this one is not among them. ${safariBackgroundDies}`,
|
|
1292
|
+
'windows.onBoundsChanged': `Safari raises no event when a window is moved or resized. ${safariBackgroundDies}`
|
|
1293
|
+
};
|
|
1294
|
+
function safariMemberUnsupported(file, api, member, kind) {
|
|
1295
|
+
const guard = 'call' === kind ? `chrome.${api}.${member}?.()` : `chrome.${api}.${member}?.`;
|
|
1296
|
+
const lines = [];
|
|
1297
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} calls chrome.${api}.${member}, which Safari does not have.`);
|
|
1298
|
+
lines.push(safariMissingMemberDetails[`${api}.${member}`] || `Safari ships chrome.${api} without this member. ${safariBackgroundDies}`);
|
|
1299
|
+
lines.push(`Safari has ${pintor.blue(`chrome.${api}`)} itself, so a guard on the namespace does not help. Move the call behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')}, or guard it with ${pintor.yellow(guard)}.`);
|
|
1300
|
+
return lines.join('\n');
|
|
1301
|
+
}
|
|
1302
|
+
function geckoActionUnsupportedOnMv2(file) {
|
|
1303
|
+
const lines = [];
|
|
1304
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.action, which Manifest V2 does not have on Firefox.`);
|
|
1305
|
+
lines.push("Firefox Manifest V2 exposes the toolbar button as browserAction, and addons-linter flags the call as UNSUPPORTED_API.");
|
|
1306
|
+
lines.push(`Use browserAction behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')}, or declare Manifest V3 for Firefox with ${pintor.yellow('firefox:manifest_version')}.`);
|
|
1307
|
+
return lines.join('\n');
|
|
1308
|
+
}
|
|
1309
|
+
function webkitUnsupportedKeysDropped(browser, dropped) {
|
|
1310
|
+
const count = dropped.length;
|
|
1311
|
+
const lines = [];
|
|
1312
|
+
lines.push(`${messaging_prefix('warn')} Safari has no support for ${String(count)} manifest ${1 === count ? 'key' : 'keys'} this build inherited from its Chromium manifest, so the ${pintor.blue(browser)} build dropped ${1 === count ? 'it' : 'them'}.`);
|
|
1313
|
+
for (const entry of dropped)lines.push(`${pintor.yellow(entry.path)} ${pintor.gray(entry.reason)}`);
|
|
1314
|
+
lines.push(`Every key above is inert on Safari, so the built app lost nothing it could have run. Declare a Safari-only replacement with the ${pintor.yellow('safari:')} prefix if you have one.`);
|
|
1315
|
+
return lines.join('\n');
|
|
1316
|
+
}
|
|
1317
|
+
const UNSUPPORTED_TOP_LEVEL_KEYS = {
|
|
1318
|
+
side_panel: 'Safari has no side panel surface',
|
|
1319
|
+
sandbox: 'Safari cannot run sandboxed extension pages',
|
|
1320
|
+
user_scripts: 'Safari has no userScripts API',
|
|
1321
|
+
omnibox: 'Safari has no omnibox keyword API',
|
|
1322
|
+
chrome_settings_overrides: 'Safari lets no extension override these settings',
|
|
1323
|
+
tts_engine: 'Safari has no speech engine API',
|
|
1324
|
+
file_browser_handlers: 'ChromeOS only',
|
|
1325
|
+
input_components: 'ChromeOS only',
|
|
1326
|
+
cross_origin_embedder_policy: 'Safari reads no COEP key from a manifest',
|
|
1327
|
+
cross_origin_opener_policy: 'Safari reads no COOP key from a manifest',
|
|
1328
|
+
requirements: 'Chrome Web Store only',
|
|
1329
|
+
oauth2: 'Safari has no identity API to consume it',
|
|
1330
|
+
nacl_modules: 'Native Client is Chrome only',
|
|
1331
|
+
replacement_web_app: 'Chrome Web Store only',
|
|
1332
|
+
offline_enabled: 'Chrome Web Store only',
|
|
1333
|
+
differential_fingerprint: 'Chrome Web Store only',
|
|
1334
|
+
incognito: 'Safari always runs extensions in spanning mode and ignores the declared value'
|
|
1335
|
+
};
|
|
1336
|
+
const UNSUPPORTED_PERMISSIONS = new Set([
|
|
1337
|
+
'accessibilityFeatures.modify',
|
|
1338
|
+
'accessibilityFeatures.read',
|
|
1339
|
+
'audio',
|
|
1340
|
+
'background',
|
|
1341
|
+
'bookmarks',
|
|
1342
|
+
'browsingData',
|
|
1343
|
+
'certificateProvider',
|
|
1344
|
+
'clipboardRead',
|
|
1345
|
+
'contentSettings',
|
|
1346
|
+
'debugger',
|
|
1347
|
+
'declarativeContent',
|
|
1348
|
+
'desktopCapture',
|
|
1349
|
+
'documentScan',
|
|
1350
|
+
'downloads',
|
|
1351
|
+
'enterprise.deviceAttributes',
|
|
1352
|
+
'enterprise.platformKeys',
|
|
1353
|
+
'experimental',
|
|
1354
|
+
'favicon',
|
|
1355
|
+
'fileSystemProvider',
|
|
1356
|
+
'fontSettings',
|
|
1357
|
+
'gcm',
|
|
1358
|
+
'geolocation',
|
|
1359
|
+
'history',
|
|
1360
|
+
'identity',
|
|
1361
|
+
'identity.email',
|
|
1362
|
+
'idle',
|
|
1363
|
+
'management',
|
|
1364
|
+
'notifications',
|
|
1365
|
+
'offscreen',
|
|
1366
|
+
'pageCapture',
|
|
1367
|
+
'platformKeys',
|
|
1368
|
+
'power',
|
|
1369
|
+
'printerProvider',
|
|
1370
|
+
'privacy',
|
|
1371
|
+
'processes',
|
|
1372
|
+
'proxy',
|
|
1373
|
+
'readingList',
|
|
1374
|
+
'search',
|
|
1375
|
+
'sessions',
|
|
1376
|
+
'sidePanel',
|
|
1377
|
+
'system.cpu',
|
|
1378
|
+
'system.display',
|
|
1379
|
+
'system.memory',
|
|
1380
|
+
'system.storage',
|
|
1381
|
+
'systemLog',
|
|
1382
|
+
'tabCapture',
|
|
1383
|
+
'tabGroups',
|
|
1384
|
+
'topSites',
|
|
1385
|
+
'tts',
|
|
1386
|
+
'ttsEngine',
|
|
1387
|
+
'userScripts',
|
|
1388
|
+
'vpnProvider',
|
|
1389
|
+
'wallpaper',
|
|
1390
|
+
'webAuthenticationProxy',
|
|
1391
|
+
'webRequestBlocking'
|
|
1392
|
+
]);
|
|
1393
|
+
const PERMISSION_LISTS = [
|
|
1394
|
+
'permissions',
|
|
1395
|
+
'optional_permissions'
|
|
1396
|
+
];
|
|
1397
|
+
const UNSUPPORTED_OPTIONS_UI_KEYS = {
|
|
1398
|
+
open_in_tab: 'Safari always opens the options page in a tab'
|
|
1399
|
+
};
|
|
1400
|
+
function isPlainObject(value) {
|
|
1401
|
+
return !!value && 'object' == typeof value && !Array.isArray(value);
|
|
1402
|
+
}
|
|
1403
|
+
function dropWebkitUnsupportedKeys(manifest, browser) {
|
|
1404
|
+
const dropped = [];
|
|
1405
|
+
if (!isWebkitBasedBrowser(String(browser))) return {
|
|
1406
|
+
manifest,
|
|
1407
|
+
dropped
|
|
1408
|
+
};
|
|
1409
|
+
const next = {
|
|
1410
|
+
...manifest
|
|
1411
|
+
};
|
|
1412
|
+
for (const [key, reason] of Object.entries(UNSUPPORTED_TOP_LEVEL_KEYS))if (key in next) {
|
|
1413
|
+
delete next[key];
|
|
1414
|
+
dropped.push({
|
|
1415
|
+
path: key,
|
|
1416
|
+
reason
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
for (const listName of PERMISSION_LISTS){
|
|
1420
|
+
const list = next[listName];
|
|
1421
|
+
if (!Array.isArray(list)) continue;
|
|
1422
|
+
const kept = list.filter((entry)=>{
|
|
1423
|
+
if ('string' != typeof entry || !UNSUPPORTED_PERMISSIONS.has(entry)) return true;
|
|
1424
|
+
dropped.push({
|
|
1425
|
+
path: `${listName}.${entry}`,
|
|
1426
|
+
reason: `Safari has no ${entry} API`
|
|
1427
|
+
});
|
|
1428
|
+
return false;
|
|
1429
|
+
});
|
|
1430
|
+
if (kept.length !== list.length) if (0 === kept.length) delete next[listName];
|
|
1431
|
+
else next[listName] = kept;
|
|
1432
|
+
}
|
|
1433
|
+
const optionsUi = next.options_ui;
|
|
1434
|
+
if (isPlainObject(optionsUi)) {
|
|
1435
|
+
const patched = {
|
|
1436
|
+
...optionsUi
|
|
1437
|
+
};
|
|
1438
|
+
let changed = false;
|
|
1439
|
+
for (const [key, reason] of Object.entries(UNSUPPORTED_OPTIONS_UI_KEYS))if (key in patched) {
|
|
1440
|
+
delete patched[key];
|
|
1441
|
+
changed = true;
|
|
1442
|
+
dropped.push({
|
|
1443
|
+
path: `options_ui.${key}`,
|
|
1444
|
+
reason
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
if (changed) next.options_ui = patched;
|
|
1448
|
+
}
|
|
1449
|
+
return {
|
|
1450
|
+
manifest: next,
|
|
1451
|
+
dropped
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
const reportedDrops = new Set();
|
|
1455
|
+
function reportWebkitDroppedKeys(dropped, browser) {
|
|
1456
|
+
if (0 === dropped.length) return;
|
|
1457
|
+
const signature = `${String(browser)}\0${dropped.map((entry)=>entry.path).join(',')}`;
|
|
1458
|
+
if (reportedDrops.has(signature)) return;
|
|
1459
|
+
reportedDrops.add(signature);
|
|
1460
|
+
humanLine(webkitUnsupportedKeysDropped(String(browser), dropped));
|
|
1461
|
+
}
|
|
1122
1462
|
const manifest_cjsRequire = createRequire(import.meta.url);
|
|
1123
1463
|
const manifestSourceStore = new WeakMap();
|
|
1124
1464
|
function manifestSourceEntry(compilation) {
|
|
@@ -1185,12 +1525,22 @@ function getManifestContent(compilation, manifestPath) {
|
|
|
1185
1525
|
function buildCanonicalManifest(manifestPath, manifest, browser, projectPath) {
|
|
1186
1526
|
const filteredManifest = filterKeysForThisBrowser(manifest, browser);
|
|
1187
1527
|
const forOverrides = shouldDropPageAction(filteredManifest, browser) ? dropPageAction(filteredManifest) : filteredManifest;
|
|
1188
|
-
|
|
1528
|
+
const canonical = dropMv2ObjectPolicy(dropMv2HostKeys({
|
|
1189
1529
|
...forOverrides,
|
|
1190
1530
|
...JSON.parse(getManifestOverrides(manifestPath, forOverrides, projectPath))
|
|
1191
1531
|
}));
|
|
1532
|
+
const webkit = dropWebkitUnsupportedKeys(canonical, browser);
|
|
1533
|
+
reportWebkitDroppedKeys(webkit.dropped, browser);
|
|
1534
|
+
return webkit.manifest;
|
|
1192
1535
|
}
|
|
1193
1536
|
const IMPORT_META_URL_RUNTIME = '(function(){var h=typeof document!=="undefined"&&document.baseURI||self.location.href;try{var g=globalThis,r=(g.browser||g.chrome).runtime.getURL("/");return h.indexOf(r)===0?h:r}catch(_){return h}})()';
|
|
1537
|
+
function importMetaUrlForEmitPath(emitPath) {
|
|
1538
|
+
const request = emitPath.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
1539
|
+
return `(function(){try{var g=globalThis;return (g.browser||g.chrome).runtime.getURL(${toJsStringLiteral(request)})}catch(_){return ${IMPORT_META_URL_RUNTIME}}})()`;
|
|
1540
|
+
}
|
|
1541
|
+
function toJsStringLiteral(value) {
|
|
1542
|
+
return JSON.stringify(value).replace(/[<>\u007f-\uffff]/g, (char)=>`\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
|
1543
|
+
}
|
|
1194
1544
|
function resolveProcessShim() {
|
|
1195
1545
|
const candidate = __rspack_external_node_path_806ed179.join(__rspack_import_meta_dirname__, '..', 'runtime', 'process-shim.cjs');
|
|
1196
1546
|
try {
|
|
@@ -1303,7 +1653,6 @@ class EnvPlugin {
|
|
|
1303
1653
|
filteredEnvVars['import.meta.dirname'] = 'undefined';
|
|
1304
1654
|
filteredEnvVars['import.meta.filename'] = 'undefined';
|
|
1305
1655
|
filteredEnvVars.global = 'globalThis';
|
|
1306
|
-
filteredEnvVars['import.meta.url'] = IMPORT_META_URL_RUNTIME;
|
|
1307
1656
|
const injectedCount = Object.keys(filteredEnvVars).filter((k)=>k.startsWith('process.env.EXTENSION_PUBLIC_')).length;
|
|
1308
1657
|
if (isDebug()) console.log(envInjectedPublicVars(injectedCount));
|
|
1309
1658
|
const processShim = resolveProcessShim();
|
|
@@ -1312,6 +1661,11 @@ class EnvPlugin {
|
|
|
1312
1661
|
filteredEnvVars.process = '({env:{},argv:[],platform:"browser",browser:true,versions:{},nextTick:function(cb){Promise.resolve().then(function(){cb()})}})';
|
|
1313
1662
|
}
|
|
1314
1663
|
new DefinePlugin(filteredEnvVars).apply(compiler);
|
|
1664
|
+
const importMetaUrl = new DefinePlugin({
|
|
1665
|
+
'import.meta.url': IMPORT_META_URL_RUNTIME
|
|
1666
|
+
});
|
|
1667
|
+
importMetaUrl.affectedHooks = 'thisCompilation';
|
|
1668
|
+
importMetaUrl.apply(compiler);
|
|
1315
1669
|
if (processShim) new ProvidePlugin({
|
|
1316
1670
|
process: processShim
|
|
1317
1671
|
}).apply(compiler);
|
|
@@ -2577,294 +2931,8 @@ function getResolvedManifestFieldsData(options) {
|
|
|
2577
2931
|
return data;
|
|
2578
2932
|
}
|
|
2579
2933
|
}
|
|
2580
|
-
let preact_userMessageDelivered = false;
|
|
2581
|
-
function isUsingPreact(projectPath) {
|
|
2582
|
-
if (hasDependency(projectPath, 'preact')) {
|
|
2583
|
-
if (!preact_userMessageDelivered) {
|
|
2584
|
-
if (isDebug()) console.log(`${messaging_prefix('debug')} ${messages_isUsingIntegration('Preact')}`);
|
|
2585
|
-
preact_userMessageDelivered = true;
|
|
2586
|
-
}
|
|
2587
|
-
return true;
|
|
2588
|
-
}
|
|
2589
|
-
return false;
|
|
2590
|
-
}
|
|
2591
|
-
async function maybeUsePreact(projectPath) {
|
|
2592
|
-
if (!isUsingPreact(projectPath)) return;
|
|
2593
|
-
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
2594
|
-
const resolveFromProject = (id)=>{
|
|
2595
|
-
try {
|
|
2596
|
-
return requireFromProject.resolve(id);
|
|
2597
|
-
} catch {
|
|
2598
|
-
return;
|
|
2599
|
-
}
|
|
2600
|
-
};
|
|
2601
|
-
const preactPkgJson = resolveFromProject('preact/package.json');
|
|
2602
|
-
const preactDir = preactPkgJson ? __rspack_external_node_path_806ed179.dirname(preactPkgJson) : void 0;
|
|
2603
|
-
const preactCompat = resolveFromProject('preact/compat');
|
|
2604
|
-
const preactTestUtils = resolveFromProject('preact/test-utils');
|
|
2605
|
-
const preactJsxRuntime = resolveFromProject('preact/jsx-runtime');
|
|
2606
|
-
const preactJsxDevRuntime = resolveFromProject('preact/jsx-dev-runtime');
|
|
2607
|
-
const alias = {};
|
|
2608
|
-
if (preactJsxRuntime) alias['preact/jsx-runtime'] = preactJsxRuntime;
|
|
2609
|
-
if (preactJsxDevRuntime) alias['preact/jsx-dev-runtime'] = preactJsxDevRuntime;
|
|
2610
|
-
if (preactDir) alias.preact = preactDir;
|
|
2611
|
-
if (preactCompat) {
|
|
2612
|
-
alias.react = preactCompat;
|
|
2613
|
-
alias['react-dom'] = preactCompat;
|
|
2614
|
-
}
|
|
2615
|
-
if (preactTestUtils) alias['react-dom/test-utils'] = preactTestUtils;
|
|
2616
|
-
if (preactJsxRuntime) alias['react/jsx-runtime'] = preactJsxRuntime;
|
|
2617
|
-
if (preactJsxDevRuntime) alias['react/jsx-dev-runtime'] = preactJsxDevRuntime;
|
|
2618
|
-
return {
|
|
2619
|
-
plugins: [],
|
|
2620
|
-
loaders: void 0,
|
|
2621
|
-
alias
|
|
2622
|
-
};
|
|
2623
|
-
}
|
|
2624
|
-
let react_userMessageDelivered = false;
|
|
2625
|
-
function isUsingReact(projectPath) {
|
|
2626
|
-
if (hasDependency(projectPath, 'react')) {
|
|
2627
|
-
if (!react_userMessageDelivered) {
|
|
2628
|
-
if (isDebug()) console.log(`${messaging_prefix('debug')} ${messages_isUsingIntegration('React')}`);
|
|
2629
|
-
react_userMessageDelivered = true;
|
|
2630
|
-
}
|
|
2631
|
-
return true;
|
|
2632
|
-
}
|
|
2633
|
-
return false;
|
|
2634
|
-
}
|
|
2635
|
-
async function maybeUseReact(projectPath, options = {}) {
|
|
2636
|
-
if (!isUsingReact(projectPath)) return;
|
|
2637
|
-
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
2638
|
-
let reactPath;
|
|
2639
|
-
let reactDomPath;
|
|
2640
|
-
let reactDomClientPath;
|
|
2641
|
-
let jsxRuntimePath;
|
|
2642
|
-
let jsxDevRuntimePath;
|
|
2643
|
-
try {
|
|
2644
|
-
reactPath = requireFromProject.resolve('react');
|
|
2645
|
-
} catch {}
|
|
2646
|
-
try {
|
|
2647
|
-
reactDomPath = requireFromProject.resolve('react-dom');
|
|
2648
|
-
} catch {}
|
|
2649
|
-
try {
|
|
2650
|
-
reactDomClientPath = requireFromProject.resolve('react-dom/client');
|
|
2651
|
-
} catch {}
|
|
2652
|
-
try {
|
|
2653
|
-
jsxRuntimePath = requireFromProject.resolve('react/jsx-runtime');
|
|
2654
|
-
} catch {}
|
|
2655
|
-
try {
|
|
2656
|
-
jsxDevRuntimePath = requireFromProject.resolve('react/jsx-dev-runtime');
|
|
2657
|
-
} catch {}
|
|
2658
|
-
const alias = {};
|
|
2659
|
-
if (reactPath) alias.react$ = reactPath;
|
|
2660
|
-
if (reactDomPath) alias['react-dom$'] = reactDomPath;
|
|
2661
|
-
if (reactDomClientPath) alias['react-dom/client'] = reactDomClientPath;
|
|
2662
|
-
if (jsxRuntimePath) alias['react/jsx-runtime'] = jsxRuntimePath;
|
|
2663
|
-
if (jsxDevRuntimePath) alias['react/jsx-dev-runtime'] = jsxDevRuntimePath;
|
|
2664
|
-
if (true === options.disableRefresh) return {
|
|
2665
|
-
plugins: [],
|
|
2666
|
-
loaders: void 0,
|
|
2667
|
-
alias
|
|
2668
|
-
};
|
|
2669
|
-
resolveOptionalContractPackageWithoutInstall({
|
|
2670
|
-
contractId: 'react-refresh',
|
|
2671
|
-
projectPath,
|
|
2672
|
-
dependencyId: 'react-refresh'
|
|
2673
|
-
});
|
|
2674
|
-
const ReactRefreshPlugin = loadOptionalContractModuleWithoutInstall({
|
|
2675
|
-
contractId: 'react-refresh',
|
|
2676
|
-
projectPath,
|
|
2677
|
-
dependencyId: '@rspack/plugin-react-refresh',
|
|
2678
|
-
moduleAdapter: (mod)=>mod && (mod.default || mod.ReactRefreshRspackPlugin) || mod
|
|
2679
|
-
});
|
|
2680
|
-
const reactPlugins = [
|
|
2681
|
-
new ReactRefreshPlugin({
|
|
2682
|
-
overlay: false,
|
|
2683
|
-
...void 0 === options.refreshExclude ? {} : {
|
|
2684
|
-
exclude: options.refreshExclude
|
|
2685
|
-
}
|
|
2686
|
-
})
|
|
2687
|
-
];
|
|
2688
|
-
return {
|
|
2689
|
-
plugins: reactPlugins,
|
|
2690
|
-
loaders: void 0,
|
|
2691
|
-
alias
|
|
2692
|
-
};
|
|
2693
|
-
}
|
|
2694
|
-
let solid_userMessageDelivered = false;
|
|
2695
|
-
function isUsingSolid(projectPath) {
|
|
2696
|
-
if (hasDependency(projectPath, 'solid-js')) {
|
|
2697
|
-
if (!solid_userMessageDelivered) {
|
|
2698
|
-
if (isDebug()) console.log(`${messaging_prefix('debug')} ${messages_isUsingIntegration('Solid')}`);
|
|
2699
|
-
solid_userMessageDelivered = true;
|
|
2700
|
-
}
|
|
2701
|
-
return true;
|
|
2702
|
-
}
|
|
2703
|
-
return false;
|
|
2704
|
-
}
|
|
2705
|
-
async function maybeUseSolid(projectPath) {
|
|
2706
|
-
if (!isUsingSolid(projectPath)) return;
|
|
2707
|
-
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
2708
|
-
const resolveFromProject = (id)=>{
|
|
2709
|
-
try {
|
|
2710
|
-
return requireFromProject.resolve(id);
|
|
2711
|
-
} catch {
|
|
2712
|
-
return;
|
|
2713
|
-
}
|
|
2714
|
-
};
|
|
2715
|
-
const adapter = resolveDevelopDistFile('solid-jsx-runtime');
|
|
2716
|
-
const hyperscript = resolveFromProject('solid-js/h');
|
|
2717
|
-
const alias = {
|
|
2718
|
-
'solid-js/jsx-runtime$': adapter,
|
|
2719
|
-
'solid-js/jsx-dev-runtime$': adapter
|
|
2720
|
-
};
|
|
2721
|
-
if (hyperscript) alias['solid-js/h$'] = hyperscript;
|
|
2722
|
-
return {
|
|
2723
|
-
plugins: [],
|
|
2724
|
-
loaders: void 0,
|
|
2725
|
-
alias
|
|
2726
|
-
};
|
|
2727
|
-
}
|
|
2728
|
-
let load_loader_options_userMessageDelivered = false;
|
|
2729
|
-
function resolveLoaderConfigPath(projectPath, framework) {
|
|
2730
|
-
const candidates = [
|
|
2731
|
-
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.ts`),
|
|
2732
|
-
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.mts`),
|
|
2733
|
-
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.js`),
|
|
2734
|
-
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.mjs`)
|
|
2735
|
-
];
|
|
2736
|
-
return candidates.find((p)=>__rspack_external_node_fs_1b05aee1.existsSync(p)) || null;
|
|
2737
|
-
}
|
|
2738
|
-
async function loadLoaderOptions(projectPath, framework) {
|
|
2739
|
-
const configPath = resolveLoaderConfigPath(projectPath, framework);
|
|
2740
|
-
if (configPath) {
|
|
2741
|
-
if (!load_loader_options_userMessageDelivered && isDebug()) {
|
|
2742
|
-
const display = __rspack_external_node_path_806ed179.basename(configPath);
|
|
2743
|
-
console.log(isUsingCustomLoader(display));
|
|
2744
|
-
load_loader_options_userMessageDelivered = true;
|
|
2745
|
-
}
|
|
2746
|
-
try {
|
|
2747
|
-
const module = await import(pathToFileURL(configPath).href);
|
|
2748
|
-
return module.default || module;
|
|
2749
|
-
} catch (err) {
|
|
2750
|
-
const error = err;
|
|
2751
|
-
console.error(`Error loading ${framework} loader options: ${error.message}`);
|
|
2752
|
-
throw err;
|
|
2753
|
-
}
|
|
2754
|
-
}
|
|
2755
|
-
return null;
|
|
2756
|
-
}
|
|
2757
|
-
let vue_userMessageDelivered = false;
|
|
2758
|
-
function isUsingVue(projectPath) {
|
|
2759
|
-
const using = hasDependency(projectPath, 'vue');
|
|
2760
|
-
if (using && !vue_userMessageDelivered) {
|
|
2761
|
-
if (isDebug()) console.log(`${messaging_prefix('debug')} ${messages_isUsingIntegration('Vue')}`);
|
|
2762
|
-
vue_userMessageDelivered = true;
|
|
2763
|
-
}
|
|
2764
|
-
return using;
|
|
2765
|
-
}
|
|
2766
|
-
function resolveVueBundlerEntry(requireFromProject, id) {
|
|
2767
|
-
try {
|
|
2768
|
-
const manifestPath = requireFromProject.resolve(`${id}/package.json`);
|
|
2769
|
-
const manifest = JSON.parse(__rspack_external_node_fs_1b05aee1.readFileSync(manifestPath, 'utf8'));
|
|
2770
|
-
if ('string' == typeof manifest.module && manifest.module) {
|
|
2771
|
-
const entry = __rspack_external_node_path_806ed179.join(__rspack_external_node_path_806ed179.dirname(manifestPath), manifest.module);
|
|
2772
|
-
if (__rspack_external_node_fs_1b05aee1.existsSync(entry)) return entry;
|
|
2773
|
-
}
|
|
2774
|
-
} catch {}
|
|
2775
|
-
try {
|
|
2776
|
-
return requireFromProject.resolve(id);
|
|
2777
|
-
} catch {
|
|
2778
|
-
return;
|
|
2779
|
-
}
|
|
2780
|
-
}
|
|
2781
|
-
async function maybeUseVue(projectPath, mode = 'development') {
|
|
2782
|
-
if (!isUsingVue(projectPath)) return;
|
|
2783
|
-
const vueLoaderPath = await ensureOptionalContractPackageResolved({
|
|
2784
|
-
contractId: 'vue',
|
|
2785
|
-
projectPath,
|
|
2786
|
-
dependencyId: 'vue-loader'
|
|
2787
|
-
});
|
|
2788
|
-
const VueLoaderPlugin = await ensureOptionalContractModuleLoaded({
|
|
2789
|
-
contractId: 'vue',
|
|
2790
|
-
projectPath,
|
|
2791
|
-
dependencyId: 'vue-loader',
|
|
2792
|
-
moduleAdapter: (mod)=>mod?.VueLoaderPlugin || mod?.default?.VueLoaderPlugin
|
|
2793
|
-
});
|
|
2794
|
-
const customOptions = await loadLoaderOptions(projectPath, 'vue');
|
|
2795
|
-
const defaultLoaders = [
|
|
2796
|
-
{
|
|
2797
|
-
test: /\.vue$/,
|
|
2798
|
-
loader: vueLoaderPath,
|
|
2799
|
-
options: {
|
|
2800
|
-
experimentalInlineMatchResource: true,
|
|
2801
|
-
...customOptions || {}
|
|
2802
|
-
},
|
|
2803
|
-
include: projectPath,
|
|
2804
|
-
exclude: /node_modules/
|
|
2805
|
-
}
|
|
2806
|
-
];
|
|
2807
|
-
const isProd = 'production' === mode;
|
|
2808
|
-
const defaultPlugins = [
|
|
2809
|
-
new VueLoaderPlugin(),
|
|
2810
|
-
new DefinePlugin({
|
|
2811
|
-
__VUE_OPTIONS_API__: JSON.stringify(true),
|
|
2812
|
-
__VUE_PROD_DEVTOOLS__: JSON.stringify(!isProd),
|
|
2813
|
-
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(!isProd)
|
|
2814
|
-
})
|
|
2815
|
-
];
|
|
2816
|
-
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
2817
|
-
const resolveFromProject = (id)=>resolveVueBundlerEntry(requireFromProject, id);
|
|
2818
|
-
const alias = {};
|
|
2819
|
-
const vuePath = resolveFromProject('vue');
|
|
2820
|
-
const vueRuntimeDom = resolveFromProject('@vue/runtime-dom');
|
|
2821
|
-
const vueRuntimeCore = resolveFromProject('@vue/runtime-core');
|
|
2822
|
-
const vueShared = resolveFromProject('@vue/shared');
|
|
2823
|
-
if (vuePath) alias.vue$ = vuePath;
|
|
2824
|
-
if (vueRuntimeDom) alias['@vue/runtime-dom'] = vueRuntimeDom;
|
|
2825
|
-
if (vueRuntimeCore) alias['@vue/runtime-core'] = vueRuntimeCore;
|
|
2826
|
-
if (vueShared) alias['@vue/shared'] = vueShared;
|
|
2827
|
-
return {
|
|
2828
|
-
plugins: defaultPlugins,
|
|
2829
|
-
loaders: defaultLoaders,
|
|
2830
|
-
alias
|
|
2831
|
-
};
|
|
2832
|
-
}
|
|
2833
|
-
function isUsingJsxFramework(projectPath) {
|
|
2834
|
-
return isUsingReact(projectPath) || isUsingPreact(projectPath) || isUsingSolid(projectPath) || isUsingVue(projectPath);
|
|
2835
|
-
}
|
|
2836
|
-
function getJsxImportSource(projectPath) {
|
|
2837
|
-
if (isUsingSolid(projectPath)) return 'solid-js';
|
|
2838
|
-
if (isUsingPreact(projectPath) && !isUsingReact(projectPath)) return 'preact';
|
|
2839
|
-
if (isUsingVue(projectPath) && !isUsingReact(projectPath) && !isUsingPreact(projectPath)) return 'vue';
|
|
2840
|
-
return 'react';
|
|
2841
|
-
}
|
|
2842
|
-
function swcParserForFile(resourcePath, jsxInPlainJs) {
|
|
2843
|
-
const clean = String(resourcePath || '').split('?')[0];
|
|
2844
|
-
const ext = __rspack_external_node_path_806ed179.extname(clean).toLowerCase();
|
|
2845
|
-
if ('.tsx' === ext || '.mtsx' === ext) return {
|
|
2846
|
-
syntax: "typescript",
|
|
2847
|
-
tsx: true,
|
|
2848
|
-
dynamicImport: true
|
|
2849
|
-
};
|
|
2850
|
-
if ('.ts' === ext || '.mts' === ext || '.cts' === ext) return {
|
|
2851
|
-
syntax: "typescript",
|
|
2852
|
-
tsx: false,
|
|
2853
|
-
dynamicImport: true
|
|
2854
|
-
};
|
|
2855
|
-
if ('.jsx' === ext || '.mjsx' === ext) return {
|
|
2856
|
-
syntax: "ecmascript",
|
|
2857
|
-
jsx: true,
|
|
2858
|
-
dynamicImport: true
|
|
2859
|
-
};
|
|
2860
|
-
return {
|
|
2861
|
-
syntax: "ecmascript",
|
|
2862
|
-
jsx: jsxInPlainJs,
|
|
2863
|
-
dynamicImport: true
|
|
2864
|
-
};
|
|
2865
|
-
}
|
|
2866
2934
|
let svelte_userMessageDelivered = false;
|
|
2867
|
-
function
|
|
2935
|
+
function resolveFromProject(id, projectPath) {
|
|
2868
2936
|
for (const base of [
|
|
2869
2937
|
projectPath,
|
|
2870
2938
|
process.cwd()
|
|
@@ -2921,10 +2989,10 @@ async function maybeUseSvelte(projectPath, mode) {
|
|
|
2921
2989
|
}
|
|
2922
2990
|
}
|
|
2923
2991
|
];
|
|
2924
|
-
const sveltePackageJson =
|
|
2992
|
+
const sveltePackageJson = resolveFromProject('svelte/package.json', projectPath);
|
|
2925
2993
|
const sveltePackageRoot = sveltePackageJson ? __rspack_external_node_path_806ed179.dirname(sveltePackageJson) : void 0;
|
|
2926
2994
|
const resolveClientSubpath = (relative)=>{
|
|
2927
|
-
const direct =
|
|
2995
|
+
const direct = resolveFromProject(`svelte/${relative}`, projectPath);
|
|
2928
2996
|
if (direct) return direct;
|
|
2929
2997
|
if (!sveltePackageRoot) return;
|
|
2930
2998
|
const fromRoot = __rspack_external_node_path_806ed179.join(sveltePackageRoot, relative);
|
|
@@ -3531,14 +3599,28 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3531
3599
|
var connectFailures = 0;
|
|
3532
3600
|
var MAX_QUEUE = 1000;
|
|
3533
3601
|
var MAX_RESULT_BYTES = 256 * 1024;
|
|
3602
|
+
// Where error frames are parked so a context that dies before its socket
|
|
3603
|
+
// opens does not take them along. Capped, and old entries are dropped.
|
|
3604
|
+
var PENDING_ERRORS_KEY = "__extjsPendingErrors";
|
|
3605
|
+
var MAX_PENDING_ERRORS = 20;
|
|
3606
|
+
var PENDING_ERROR_TTL = 300000;
|
|
3534
3607
|
|
|
3535
3608
|
function nowId() {
|
|
3536
3609
|
return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
3537
3610
|
}
|
|
3538
3611
|
|
|
3612
|
+
// The extension's own URL scheme names the engine outright, which beats a
|
|
3613
|
+
// user agent where Chrome and Safari both say "Safari".
|
|
3539
3614
|
function engineName() {
|
|
3540
3615
|
try {
|
|
3541
|
-
|
|
3616
|
+
var scheme = (typeof location !== "undefined" && location.protocol) || "";
|
|
3617
|
+
if (scheme.indexOf("safari-web-extension") === 0) return "webkit";
|
|
3618
|
+
if (scheme.indexOf("moz-extension") === 0) return "firefox";
|
|
3619
|
+
if (scheme.indexOf("chrome-extension") === 0) return "chromium";
|
|
3620
|
+
var ua = (typeof navigator !== "undefined" && navigator.userAgent) || "";
|
|
3621
|
+
if (/firefox/i.test(ua)) return "firefox";
|
|
3622
|
+
if (/safari/i.test(ua) && !/chrome|chromium|edg/i.test(ua)) return "webkit";
|
|
3623
|
+
return "chromium";
|
|
3542
3624
|
} catch (e) { return "chromium"; }
|
|
3543
3625
|
}
|
|
3544
3626
|
|
|
@@ -3687,7 +3769,7 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3687
3769
|
// MV3 forbids eval of strings in the SW/extension pages and
|
|
3688
3770
|
// rejects 'unsafe-eval'. Surface it honestly with an alternative.
|
|
3689
3771
|
if (/Content Security Policy|unsafe-eval/i.test(msg)) {
|
|
3690
|
-
replyErr(cmdId, "Unsupported", "eval is blocked in the
|
|
3772
|
+
replyErr(cmdId, "Unsupported", "eval is blocked in the extension background by CSP, which allows no unsafe-eval. Use --context page --tab <id> (eval runs in the page's MAIN world), or run on a build whose CSP permits it. Engine: " + engineName());
|
|
3691
3773
|
} else {
|
|
3692
3774
|
replyErr(cmdId, (e && e.name) || "EvalError", msg);
|
|
3693
3775
|
}
|
|
@@ -3837,6 +3919,11 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3837
3919
|
try { chrome.runtime.openOptionsPage(function () { replyOk(cmdId, {opened: "options"}); }); }
|
|
3838
3920
|
catch (e) { replyErr(cmdId, "Unsupported", "openOptionsPage: " + e); }
|
|
3839
3921
|
} else if (surface === "sidebar") {
|
|
3922
|
+
// The two member reads below are exactly what the Safari
|
|
3923
|
+
// unsupported-API scan looks for, and this runtime is prepended to
|
|
3924
|
+
// the background asset at PROCESS_ASSETS_STAGE_REPORT + 101, after
|
|
3925
|
+
// that scan runs at SUMMARIZE + 1. Move the injection earlier and
|
|
3926
|
+
// every Safari dev session warns about this line.
|
|
3840
3927
|
if (chrome.sidePanel && chrome.sidePanel.open && chrome.windows) {
|
|
3841
3928
|
chrome.windows.getCurrent(function (w) {
|
|
3842
3929
|
nsCall("sidePanel", "open", [{windowId: w.id}], function (err) {
|
|
@@ -4289,6 +4376,80 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
4289
4376
|
}
|
|
4290
4377
|
}
|
|
4291
4378
|
if (queue.length < MAX_QUEUE) queue.push(frame);
|
|
4379
|
+
parkPendingError(frame);
|
|
4380
|
+
}
|
|
4381
|
+
|
|
4382
|
+
// The queue above lives in this context's memory only, so a background
|
|
4383
|
+
// that throws while it evaluates dies with the error still queued: the
|
|
4384
|
+
// socket has not finished its handshake yet. Park error frames in
|
|
4385
|
+
// extension storage too, where the NEXT context to connect can ship them.
|
|
4386
|
+
// Best effort by construction: the write is asynchronous, so a teardown
|
|
4387
|
+
// can cut it before the browser records anything.
|
|
4388
|
+
var parkedErrors = [];
|
|
4389
|
+
function storageLocalArea() {
|
|
4390
|
+
try {
|
|
4391
|
+
var ns = (g.chrome && g.chrome.storage) || (g.browser && g.browser.storage);
|
|
4392
|
+
var area = ns && ns.local;
|
|
4393
|
+
if (!area || typeof area.get !== "function" || typeof area.set !== "function") return null;
|
|
4394
|
+
return area;
|
|
4395
|
+
} catch (e) { return null; }
|
|
4396
|
+
}
|
|
4397
|
+
function parkPendingError(frame) {
|
|
4398
|
+
if (open) return;
|
|
4399
|
+
if (!frame || frame.type !== "log" || !frame.event || frame.event.level !== "error") return;
|
|
4400
|
+
var area = storageLocalArea();
|
|
4401
|
+
if (!area) return;
|
|
4402
|
+
// The whole list is rewritten on every park, so two errors in one turn
|
|
4403
|
+
// cannot lose each other to a read-modify-write, and the cap holds.
|
|
4404
|
+
parkedErrors.push(frame);
|
|
4405
|
+
while (parkedErrors.length > MAX_PENDING_ERRORS) parkedErrors.shift();
|
|
4406
|
+
var items = {};
|
|
4407
|
+
items[PENDING_ERRORS_KEY] = parkedErrors;
|
|
4408
|
+
try { area.set(items, noopLastError); } catch (e) {
|
|
4409
|
+
// Ignore
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
function parkedHere(id) {
|
|
4413
|
+
for (var i = 0; i < parkedErrors.length; i++) {
|
|
4414
|
+
var ev = parkedErrors[i] && parkedErrors[i].event;
|
|
4415
|
+
if (ev && ev.id === id) return true;
|
|
4416
|
+
}
|
|
4417
|
+
return false;
|
|
4418
|
+
}
|
|
4419
|
+
// Ship what an earlier context parked and never got to send. Entries from
|
|
4420
|
+
// another build (a different instance id) or from an older run are dropped,
|
|
4421
|
+
// and the key is cleared on read so one failure is reported once.
|
|
4422
|
+
function flushPendingErrors() {
|
|
4423
|
+
var area = storageLocalArea();
|
|
4424
|
+
if (!area) return;
|
|
4425
|
+
var read = false;
|
|
4426
|
+
function onRead(res) {
|
|
4427
|
+
if (read) return;
|
|
4428
|
+
read = true;
|
|
4429
|
+
var list = res && res[PENDING_ERRORS_KEY];
|
|
4430
|
+
if (!list || !list.length) return;
|
|
4431
|
+
try {
|
|
4432
|
+
if (typeof area.remove === "function") area.remove(PENDING_ERRORS_KEY, noopLastError);
|
|
4433
|
+
} catch (e) {
|
|
4434
|
+
// Ignore
|
|
4435
|
+
}
|
|
4436
|
+
var now = Date.now();
|
|
4437
|
+
for (var i = 0; i < list.length; i++) {
|
|
4438
|
+
var frame = list[i];
|
|
4439
|
+
var ev = frame && frame.event;
|
|
4440
|
+
if (!ev || ev.runId !== INSTANCE_ID) continue;
|
|
4441
|
+
// This context parked it, so the queue flush above already has it.
|
|
4442
|
+
if (parkedHere(ev.id)) continue;
|
|
4443
|
+
if (typeof ev.timestamp !== "number" || now - ev.timestamp > PENDING_ERROR_TTL) continue;
|
|
4444
|
+
send(frame);
|
|
4445
|
+
}
|
|
4446
|
+
}
|
|
4447
|
+
try {
|
|
4448
|
+
var ret = area.get(PENDING_ERRORS_KEY, function (res) { noopLastError(); onRead(res); });
|
|
4449
|
+
if (ret && typeof ret.then === "function") ret.then(onRead, function () {});
|
|
4450
|
+
} catch (e) {
|
|
4451
|
+
// Ignore
|
|
4452
|
+
}
|
|
4292
4453
|
}
|
|
4293
4454
|
|
|
4294
4455
|
// The baked PORT is a snapshot of an ephemeral port. After a dev-server
|
|
@@ -4342,6 +4503,9 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
4342
4503
|
// Ignore
|
|
4343
4504
|
}
|
|
4344
4505
|
flush();
|
|
4506
|
+
// Hello went first and this context's own queue is out; now replay any
|
|
4507
|
+
// error a previous context parked before it died.
|
|
4508
|
+
flushPendingErrors();
|
|
4345
4509
|
};
|
|
4346
4510
|
socket.onmessage = function (ev) {
|
|
4347
4511
|
var frame;
|
|
@@ -4809,10 +4973,12 @@ class InjectBridgeProducer {
|
|
|
4809
4973
|
name: InjectBridgeProducer.name,
|
|
4810
4974
|
stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 101
|
|
4811
4975
|
}, ()=>{
|
|
4812
|
-
|
|
4976
|
+
const controlAsset = new core_sources.RawSource(JSON.stringify({
|
|
4813
4977
|
port: controlPort,
|
|
4814
4978
|
instanceId
|
|
4815
|
-
}))
|
|
4979
|
+
}));
|
|
4980
|
+
if (compilation.getAsset(CONTROL_PORT_ASSET_NAME)) compilation.updateAsset(CONTROL_PORT_ASSET_NAME, controlAsset);
|
|
4981
|
+
else compilation.emitAsset(CONTROL_PORT_ASSET_NAME, controlAsset);
|
|
4816
4982
|
for (const asset of compilation.getAssets()){
|
|
4817
4983
|
if (!BACKGROUND_ASSET.test(asset.name)) continue;
|
|
4818
4984
|
const original = asset.source.source().toString();
|
|
@@ -6756,16 +6922,10 @@ class TraceRun {
|
|
|
6756
6922
|
async function compileRuntimeLoadedFiles(compilation, compiler, requests) {
|
|
6757
6923
|
if (0 === requests.length) return [];
|
|
6758
6924
|
const before = new Set(compilation.getAssets().map((asset)=>asset.name));
|
|
6759
|
-
for (const
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
const group = requests.filter((request)=>request.format === format);
|
|
6764
|
-
if (0 !== group.length) await compileTracedFiles({
|
|
6765
|
-
compilation,
|
|
6766
|
-
compiler
|
|
6767
|
-
}, format, group);
|
|
6768
|
-
}
|
|
6925
|
+
for (const request of requests)await compileTracedFile({
|
|
6926
|
+
compilation,
|
|
6927
|
+
compiler
|
|
6928
|
+
}, request);
|
|
6769
6929
|
return compilation.getAssets().map((asset)=>asset.name).filter((name)=>!before.has(name));
|
|
6770
6930
|
}
|
|
6771
6931
|
function planTracedFile(opts) {
|
|
@@ -6849,21 +7009,24 @@ function isFile(candidate) {
|
|
|
6849
7009
|
return false;
|
|
6850
7010
|
}
|
|
6851
7011
|
}
|
|
6852
|
-
async function
|
|
7012
|
+
async function compileTracedFile(host, request) {
|
|
6853
7013
|
const { compilation, compiler } = host;
|
|
6854
|
-
const isModule = 'module' === format;
|
|
6855
|
-
const
|
|
6856
|
-
const
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
const
|
|
7014
|
+
const isModule = 'module' === request.format;
|
|
7015
|
+
const chunkLoading = isModule ? 'import' : 'importScripts' === request.context ? "import-scripts" : 'jsonp';
|
|
7016
|
+
const entry = new EntryPlugin(compiler.context, request.sourcePath, {
|
|
7017
|
+
name: request.emitPath.replace(/\.[^./]+$/, ''),
|
|
7018
|
+
filename: request.emitPath,
|
|
7019
|
+
chunkLoading,
|
|
7020
|
+
...isModule ? {
|
|
7021
|
+
library: {
|
|
7022
|
+
type: 'module'
|
|
7023
|
+
}
|
|
7024
|
+
} : {}
|
|
7025
|
+
});
|
|
7026
|
+
const importMetaUrl = new DefinePlugin({
|
|
7027
|
+
'import.meta.url': importMetaUrlForEmitPath(request.emitPath)
|
|
7028
|
+
});
|
|
7029
|
+
const child = compilation.createChildCompiler(`${TraceRuntimeLoadedFiles.name}:${request.format}`, {
|
|
6867
7030
|
filename: '[name].js',
|
|
6868
7031
|
module: isModule,
|
|
6869
7032
|
iife: false,
|
|
@@ -6873,8 +7036,11 @@ async function compileTracedFiles(host, format, requests) {
|
|
|
6873
7036
|
type: 'module'
|
|
6874
7037
|
} : void 0,
|
|
6875
7038
|
clean: false
|
|
6876
|
-
},
|
|
6877
|
-
|
|
7039
|
+
}, [
|
|
7040
|
+
entry,
|
|
7041
|
+
importMetaUrl
|
|
7042
|
+
]);
|
|
7043
|
+
new core_javascript.EnableChunkLoadingPlugin(chunkLoading).apply(child);
|
|
6878
7044
|
if (isModule) new library.EnableLibraryPlugin('module').apply(child);
|
|
6879
7045
|
child.options.entry = {};
|
|
6880
7046
|
child.options.optimization = {
|
|
@@ -6890,7 +7056,7 @@ async function compileTracedFiles(host, format, requests) {
|
|
|
6890
7056
|
await new Promise((resolve)=>{
|
|
6891
7057
|
child.runAsChild((error, _entries, childCompilation)=>{
|
|
6892
7058
|
if (error) {
|
|
6893
|
-
const failure = new core_WebpackError(`Compiling runtime-loaded ${
|
|
7059
|
+
const failure = new core_WebpackError(`Compiling runtime-loaded ${request.emitPath} failed: ${error.message}`);
|
|
6894
7060
|
failure.name = 'RuntimeLoadedFileCompileFailed';
|
|
6895
7061
|
compilation.errors.push(failure);
|
|
6896
7062
|
}
|
|
@@ -9537,17 +9703,17 @@ function isManagedSchemaFeature(feature) {
|
|
|
9537
9703
|
function isCriticalJsonFeature(feature) {
|
|
9538
9704
|
return feature.startsWith('declarative_net_request') || isManagedSchemaFeature(feature);
|
|
9539
9705
|
}
|
|
9540
|
-
function
|
|
9706
|
+
function json_validation_isPlainObject(value) {
|
|
9541
9707
|
return 'object' == typeof value && null !== value && !Array.isArray(value);
|
|
9542
9708
|
}
|
|
9543
9709
|
function getDnrRuleRejection(rule) {
|
|
9544
|
-
if (!
|
|
9710
|
+
if (!json_validation_isPlainObject(rule)) return 'the rule is not an object';
|
|
9545
9711
|
const id = rule.id;
|
|
9546
9712
|
if ('number' != typeof id || !Number.isInteger(id) || id < 1) return 'the rule id is not a positive integer';
|
|
9547
9713
|
const action = rule.action;
|
|
9548
|
-
if (!
|
|
9714
|
+
if (!json_validation_isPlainObject(action)) return 'the rule has no action object';
|
|
9549
9715
|
if ('string' != typeof action.type || 0 === action.type.length) return 'the rule action has no type';
|
|
9550
|
-
if (!
|
|
9716
|
+
if (!json_validation_isPlainObject(rule.condition)) return 'the rule has no condition object';
|
|
9551
9717
|
}
|
|
9552
9718
|
function getDnrRuleSoftIssue(rule) {
|
|
9553
9719
|
const priority = rule.priority;
|
|
@@ -10060,99 +10226,6 @@ class LocalesPlugin {
|
|
|
10060
10226
|
});
|
|
10061
10227
|
}
|
|
10062
10228
|
}
|
|
10063
|
-
function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
|
|
10064
|
-
const lines = [];
|
|
10065
|
-
lines.push("Entrypoint references changed.");
|
|
10066
|
-
if (fileRemoved) lines.push(`${pintor.gray('EXPECTED')} ${pintor.underline(fileRemoved)}`);
|
|
10067
|
-
if (fileAdded) lines.push(`${pintor.gray('GOT')} ${pintor.underline(fileAdded)}`);
|
|
10068
|
-
lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
|
|
10069
|
-
return lines.join('\n');
|
|
10070
|
-
}
|
|
10071
|
-
function legacyManifestPathWarning(field, legacyPath, modernPath) {
|
|
10072
|
-
const lines = [];
|
|
10073
|
-
lines.push(`${messaging_prefix('warn')} The ${pintor.blue(field)} field uses a deprecated scaffold path.`);
|
|
10074
|
-
lines.push(`${pintor.gray('PATH')} ${pintor.underline(legacyPath)}`);
|
|
10075
|
-
lines.push(`Point it at ${pintor.underline(modernPath)}, Extension.js already emits the page there.`);
|
|
10076
|
-
return lines.join('\n');
|
|
10077
|
-
}
|
|
10078
|
-
function fatalManifestShapeFixed(field, detail) {
|
|
10079
|
-
const lines = [];
|
|
10080
|
-
lines.push(`${messaging_prefix('warn')} Repaired the ${pintor.blue(field)} field, which Chrome refuses to load the extension over.`);
|
|
10081
|
-
lines.push(`${pintor.gray('REASON')} ${pintor.underline(detail)}`);
|
|
10082
|
-
lines.push(`Fix the field in your ${pintor.blue('manifest.json')} file.`);
|
|
10083
|
-
return lines.join('\n');
|
|
10084
|
-
}
|
|
10085
|
-
function invalidThemeValue(field, detail, value) {
|
|
10086
|
-
const lines = [];
|
|
10087
|
-
lines.push(`Check the ${pintor.yellow(field)} field in your ${pintor.yellow('manifest.json')} file.`);
|
|
10088
|
-
lines.push(detail);
|
|
10089
|
-
lines.push(`Chrome rejects the whole extension when this value is malformed.\nThe build stops here to protect you.`);
|
|
10090
|
-
lines.push('');
|
|
10091
|
-
lines.push(`${pintor.red('INVALID VALUE')} ${value}`);
|
|
10092
|
-
return lines.join('\n');
|
|
10093
|
-
}
|
|
10094
|
-
function themeNotSupportedByBrowser(browser) {
|
|
10095
|
-
const lines = [];
|
|
10096
|
-
lines.push(`${messaging_prefix('warn')} ${pintor.blue(browser)} does not support the ${pintor.yellow('theme')} field.`);
|
|
10097
|
-
lines.push("The field ships unchanged in the manifest and Safari ignores it.");
|
|
10098
|
-
return lines.join('\n');
|
|
10099
|
-
}
|
|
10100
|
-
function missingGeckoDataCollectionPermissions() {
|
|
10101
|
-
const lines = [];
|
|
10102
|
-
lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.blue('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
|
|
10103
|
-
lines.push(`Declare ${pintor.blue('{"required": ["none"]}')} if this extension transmits no data.`);
|
|
10104
|
-
lines.push(`See ${pintor.underline('https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/')} for details.`);
|
|
10105
|
-
return lines.join('\n');
|
|
10106
|
-
}
|
|
10107
|
-
function manifestInvalidError(error) {
|
|
10108
|
-
const lines = [];
|
|
10109
|
-
lines.push(`Can't read your ${pintor.blue('manifest.json')} file.`);
|
|
10110
|
-
lines.push(`${pintor.gray('REASON')} ${pintor.underline(String(error))}`);
|
|
10111
|
-
lines.push("Update your manifest and try again.");
|
|
10112
|
-
return lines.join('\n');
|
|
10113
|
-
}
|
|
10114
|
-
function manifestIncludeSummary(browser, manifestPath) {
|
|
10115
|
-
return `${messaging_prefix('debug')} manifest include browser=${browser} path=${manifestPath}`;
|
|
10116
|
-
}
|
|
10117
|
-
function manifestEmitSuccess() {
|
|
10118
|
-
return `${messaging_prefix('debug')} manifest emitted=true schemaStripped=true`;
|
|
10119
|
-
}
|
|
10120
|
-
function manifestOverridesSummary(overrideKeys, devCssStubsAdded) {
|
|
10121
|
-
return `${messaging_prefix('debug')} manifest overrides keys=${String(overrideKeys)} devCssStubs=${String(devCssStubsAdded)}`;
|
|
10122
|
-
}
|
|
10123
|
-
function manifestDepsTracked(addedCount) {
|
|
10124
|
-
return `${messaging_prefix('debug')} manifest deps=${String(addedCount)}`;
|
|
10125
|
-
}
|
|
10126
|
-
function manifestLegacyWarningsSummary(count) {
|
|
10127
|
-
return `${messaging_prefix('debug')} manifest legacyWarnings=${String(count)}`;
|
|
10128
|
-
}
|
|
10129
|
-
function pageActionNotSupportedByBrowser(browser) {
|
|
10130
|
-
return `${messaging_prefix('warn')} ${pintor.blue(browser)} does not show the ${pintor.yellow('page_action')} address bar surface.\nThe field was dropped from the built manifest and its page was not emitted.`;
|
|
10131
|
-
}
|
|
10132
|
-
function pageActionDroppedForBrowserAction(browser) {
|
|
10133
|
-
return `${messaging_prefix('warn')} ${pintor.blue(browser)} refuses a Manifest V2 manifest that declares both ${pintor.yellow('browser_action')} and ${pintor.yellow('page_action')}.\nThe build kept ${pintor.yellow('browser_action')} and dropped ${pintor.yellow('page_action')} from the built manifest, so its page was not emitted. Remove one of the two keys, or scope page_action with the firefox: prefix.`;
|
|
10134
|
-
}
|
|
10135
|
-
function vendorPrefixedKeyDropped(key, familyKey, vendor, browser) {
|
|
10136
|
-
const vendorName = 'edge' === vendor ? 'Edge' : 'Chrome';
|
|
10137
|
-
return `${messaging_prefix('warn')} ${pintor.yellow(key)} now applies only to ${vendorName} builds, so the ${pintor.blue(browser)} build dropped it.\nRename it to ${pintor.yellow(familyKey)} to keep it on every Chromium-based browser. Leave it as is if it's meant for ${vendorName} only.`;
|
|
10138
|
-
}
|
|
10139
|
-
function mv2SandboxPolicyDropped(browser) {
|
|
10140
|
-
return `${messaging_prefix('warn')} ${pintor.blue(browser)} reads a Manifest V2 ${pintor.yellow('content_security_policy')} as one string, so the ${pintor.yellow('sandbox')} slot has nowhere to go.\nThe build wrote the ${pintor.yellow('extension_pages')} policy as that string and dropped the sandbox policy from the built manifest. Scope the object form with the chromium: prefix, or declare a Manifest V3 build for this browser.`;
|
|
10141
|
-
}
|
|
10142
|
-
function geckoSidePanelUnsupported(file) {
|
|
10143
|
-
const lines = [];
|
|
10144
|
-
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.sidePanel, which is Chromium only.`);
|
|
10145
|
-
lines.push(`Firefox opens a sidebar through the ${pintor.yellow('sidebar_action')} manifest key on every manifest version, and addons-linter flags the call as UNSUPPORTED_API.`);
|
|
10146
|
-
lines.push(`Move the call behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')} so the Firefox bundle drops it.`);
|
|
10147
|
-
return lines.join('\n');
|
|
10148
|
-
}
|
|
10149
|
-
function geckoActionUnsupportedOnMv2(file) {
|
|
10150
|
-
const lines = [];
|
|
10151
|
-
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.action, which Manifest V2 does not have on Firefox.`);
|
|
10152
|
-
lines.push("Firefox Manifest V2 exposes the toolbar button as browserAction, and addons-linter flags the call as UNSUPPORTED_API.");
|
|
10153
|
-
lines.push(`Use browserAction behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')}, or declare Manifest V3 for Firefox with ${pintor.yellow('firefox:manifest_version')}.`);
|
|
10154
|
-
return lines.join('\n');
|
|
10155
|
-
}
|
|
10156
10229
|
class AddDependencies {
|
|
10157
10230
|
dependencyList;
|
|
10158
10231
|
constructor(dependencyList){
|
|
@@ -10333,6 +10406,71 @@ function partiallyGatedWarning(api, relative) {
|
|
|
10333
10406
|
if (!note) return null;
|
|
10334
10407
|
return `manifest.json does not declare the "${api}" permission, but ${relative} uses chrome.${api}. The dev build injects "${api}" so the same code may behave differently once packaged: ${note}. Add "${api}" to permissions in manifest.json if you read those fields.`;
|
|
10335
10408
|
}
|
|
10409
|
+
const EMITTED_SCRIPT_RE = /\.[cm]?js$/;
|
|
10410
|
+
const MAX_SOURCE_BYTES = 1048576;
|
|
10411
|
+
const MAX_ASSET_BYTES = 16777216;
|
|
10412
|
+
const MAX_COMPRESS_BYTES = 4194304;
|
|
10413
|
+
function shippableText(text) {
|
|
10414
|
+
if (text.length > MAX_COMPRESS_BYTES) return text;
|
|
10415
|
+
try {
|
|
10416
|
+
const compressed = experiments?.swc?.minifySync(text, {
|
|
10417
|
+
compress: true,
|
|
10418
|
+
mangle: false
|
|
10419
|
+
});
|
|
10420
|
+
return 'string' == typeof compressed?.code ? compressed.code : text;
|
|
10421
|
+
} catch {
|
|
10422
|
+
return text;
|
|
10423
|
+
}
|
|
10424
|
+
}
|
|
10425
|
+
function readEmittedScripts(compilation) {
|
|
10426
|
+
const scripts = new Map();
|
|
10427
|
+
let assets;
|
|
10428
|
+
try {
|
|
10429
|
+
assets = compilation.getAssets?.() || [];
|
|
10430
|
+
} catch {
|
|
10431
|
+
return scripts;
|
|
10432
|
+
}
|
|
10433
|
+
for (const asset of assets)if (EMITTED_SCRIPT_RE.test(asset.name)) try {
|
|
10434
|
+
const raw = asset.source.source();
|
|
10435
|
+
const text = 'string' == typeof raw ? raw : raw.toString('utf-8');
|
|
10436
|
+
if (text.length > MAX_ASSET_BYTES) continue;
|
|
10437
|
+
scripts.set(asset.name, text);
|
|
10438
|
+
} catch {}
|
|
10439
|
+
return scripts;
|
|
10440
|
+
}
|
|
10441
|
+
function readProjectSource(resource) {
|
|
10442
|
+
try {
|
|
10443
|
+
if (__rspack_external_node_fs_1b05aee1.statSync(resource).size > MAX_SOURCE_BYTES) return;
|
|
10444
|
+
return __rspack_external_node_fs_1b05aee1.readFileSync(resource, 'utf-8');
|
|
10445
|
+
} catch {
|
|
10446
|
+
return;
|
|
10447
|
+
}
|
|
10448
|
+
}
|
|
10449
|
+
function emittedFilesOf(compilation, module) {
|
|
10450
|
+
if (!compilation.chunkGraph) return;
|
|
10451
|
+
try {
|
|
10452
|
+
const files = [];
|
|
10453
|
+
for (const chunk of compilation.chunkGraph.getModuleChunksIterable(module))for (const file of chunk.files || [])files.push(file);
|
|
10454
|
+
return files;
|
|
10455
|
+
} catch {
|
|
10456
|
+
return;
|
|
10457
|
+
}
|
|
10458
|
+
}
|
|
10459
|
+
function patchWebkitBackground(manifest, browser) {
|
|
10460
|
+
if (!isWebkitBasedBrowser(String(browser))) return manifest;
|
|
10461
|
+
const background = manifest.background;
|
|
10462
|
+
if (!background || !background.service_worker || background.scripts) return manifest;
|
|
10463
|
+
const { service_worker, type, ...rest } = background;
|
|
10464
|
+
return {
|
|
10465
|
+
...manifest,
|
|
10466
|
+
background: {
|
|
10467
|
+
...rest,
|
|
10468
|
+
scripts: [
|
|
10469
|
+
service_worker
|
|
10470
|
+
]
|
|
10471
|
+
}
|
|
10472
|
+
};
|
|
10473
|
+
}
|
|
10336
10474
|
function persistentPatchFor(manifest) {
|
|
10337
10475
|
return 3 === manifest.manifest_version ? {} : {
|
|
10338
10476
|
persistent: true
|
|
@@ -10360,12 +10498,16 @@ function patchBackground(manifest, browser) {
|
|
|
10360
10498
|
...persistentPatchFor(manifest)
|
|
10361
10499
|
}
|
|
10362
10500
|
};
|
|
10363
|
-
|
|
10501
|
+
const injected = {
|
|
10502
|
+
...manifest,
|
|
10364
10503
|
background: {
|
|
10365
10504
|
...manifest.background || {},
|
|
10366
10505
|
service_worker: 'background/service_worker.js'
|
|
10367
10506
|
}
|
|
10368
10507
|
};
|
|
10508
|
+
return {
|
|
10509
|
+
background: patchWebkitBackground(injected, browser).background
|
|
10510
|
+
};
|
|
10369
10511
|
}
|
|
10370
10512
|
return {
|
|
10371
10513
|
background: {
|
|
@@ -10511,87 +10653,88 @@ function patchExternallyConnectable(manifest) {
|
|
|
10511
10653
|
};
|
|
10512
10654
|
return {};
|
|
10513
10655
|
}
|
|
10656
|
+
function cleanMatches(matches) {
|
|
10657
|
+
return matches.map((match)=>{
|
|
10658
|
+
try {
|
|
10659
|
+
const url = new URL(match.replace(/^\*:\/\//, 'https://'));
|
|
10660
|
+
if (match.endsWith(url.pathname)) return `${match.substring(0, match.length - url.pathname.length)}/*`;
|
|
10661
|
+
if ('/' === url.pathname) return `${match}/*`;
|
|
10662
|
+
return match;
|
|
10663
|
+
} catch {
|
|
10664
|
+
return match;
|
|
10665
|
+
}
|
|
10666
|
+
});
|
|
10667
|
+
}
|
|
10668
|
+
const DEV_RUNTIME_RESOURCES = [
|
|
10669
|
+
'hot/*',
|
|
10670
|
+
'extension-js-control.json'
|
|
10671
|
+
];
|
|
10672
|
+
function patch_web_resources_contentScriptMatches(manifest) {
|
|
10673
|
+
const scripts = manifest.content_scripts || [];
|
|
10674
|
+
return Array.from(new Set(cleanMatches(scripts.flatMap((script)=>script.matches || [])))).sort();
|
|
10675
|
+
}
|
|
10514
10676
|
function patchWebResourcesV2(manifest) {
|
|
10515
|
-
const defaultResources = [
|
|
10516
|
-
'/*.json',
|
|
10517
|
-
'/*.js',
|
|
10518
|
-
'/*.css',
|
|
10519
|
-
'/*.scss',
|
|
10520
|
-
'/*.sass',
|
|
10521
|
-
'/*.less',
|
|
10522
|
-
'*.styl',
|
|
10523
|
-
"/scripts/*.js",
|
|
10524
|
-
"/scripts/*.css",
|
|
10525
|
-
'/hot/*',
|
|
10526
|
-
'/*.png',
|
|
10527
|
-
'/*.jpg',
|
|
10528
|
-
'/*.jpeg',
|
|
10529
|
-
'/*.svg',
|
|
10530
|
-
'/*.gif',
|
|
10531
|
-
'/*.webp',
|
|
10532
|
-
'/*.ico',
|
|
10533
|
-
'/*.avif',
|
|
10534
|
-
'/*.wasm',
|
|
10535
|
-
'/*.bin'
|
|
10536
|
-
];
|
|
10537
10677
|
const resources = manifest.web_accessible_resources;
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
for (const resource of
|
|
10678
|
+
const webResources = new Set(resources || []);
|
|
10679
|
+
if (0 === patch_web_resources_contentScriptMatches(manifest).length) return Array.from(webResources);
|
|
10680
|
+
for (const resource of DEV_RUNTIME_RESOURCES)webResources.add(resource);
|
|
10541
10681
|
return Array.from(webResources);
|
|
10542
10682
|
}
|
|
10543
10683
|
function patchWebResourcesV3(manifest) {
|
|
10544
|
-
const
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
'/*.css',
|
|
10548
|
-
'/*.scss',
|
|
10549
|
-
'/*.sass',
|
|
10550
|
-
'/*.less',
|
|
10551
|
-
'*.styl',
|
|
10552
|
-
"/scripts/*.js",
|
|
10553
|
-
"/scripts/*.css",
|
|
10554
|
-
'/hot/*',
|
|
10555
|
-
'/*.png',
|
|
10556
|
-
'/*.jpg',
|
|
10557
|
-
'/*.jpeg',
|
|
10558
|
-
'/*.svg',
|
|
10559
|
-
'/*.gif',
|
|
10560
|
-
'/*.webp',
|
|
10561
|
-
'/*.ico',
|
|
10562
|
-
'/*.avif',
|
|
10563
|
-
'/*.wasm',
|
|
10564
|
-
'/*.bin'
|
|
10565
|
-
];
|
|
10684
|
+
const existing = manifest.web_accessible_resources || [];
|
|
10685
|
+
const matches = patch_web_resources_contentScriptMatches(manifest);
|
|
10686
|
+
if (0 === matches.length) return existing;
|
|
10566
10687
|
return [
|
|
10567
|
-
...
|
|
10688
|
+
...existing,
|
|
10568
10689
|
{
|
|
10569
|
-
resources:
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10690
|
+
resources: [
|
|
10691
|
+
...DEV_RUNTIME_RESOURCES
|
|
10692
|
+
],
|
|
10693
|
+
matches
|
|
10573
10694
|
}
|
|
10574
10695
|
];
|
|
10575
10696
|
}
|
|
10697
|
+
function patchWebResources(manifest) {
|
|
10698
|
+
const patched = 3 === manifest.manifest_version ? patchWebResourcesV3(manifest) : patchWebResourcesV2(manifest);
|
|
10699
|
+
if (!patched.length) return {};
|
|
10700
|
+
return {
|
|
10701
|
+
web_accessible_resources: patched
|
|
10702
|
+
};
|
|
10703
|
+
}
|
|
10576
10704
|
function findInjectedOnlyPermissionUses(compilation, declared, injected) {
|
|
10577
10705
|
const firstOffenderByApi = new Map();
|
|
10578
10706
|
const candidates = injected.filter((api)=>!declared.has(api));
|
|
10579
10707
|
if (!candidates.length) return firstOffenderByApi;
|
|
10580
|
-
|
|
10581
|
-
|
|
10582
|
-
|
|
10583
|
-
|
|
10584
|
-
|
|
10585
|
-
|
|
10586
|
-
|
|
10587
|
-
|
|
10588
|
-
|
|
10589
|
-
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10708
|
+
const emitted = readEmittedScripts(compilation);
|
|
10709
|
+
const shipped = new Map();
|
|
10710
|
+
const shippedText = (file)=>{
|
|
10711
|
+
if (shipped.has(file)) return shipped.get(file);
|
|
10712
|
+
const text = emitted.get(file);
|
|
10713
|
+
if (void 0 === text) return;
|
|
10714
|
+
const compressed = shippableText(text);
|
|
10715
|
+
shipped.set(file, compressed);
|
|
10716
|
+
return compressed;
|
|
10717
|
+
};
|
|
10718
|
+
for (const outer of compilation.modules){
|
|
10719
|
+
const inner = outer.modules ? [
|
|
10720
|
+
...outer.modules
|
|
10721
|
+
] : [
|
|
10722
|
+
outer
|
|
10723
|
+
];
|
|
10724
|
+
for (const module of inner){
|
|
10725
|
+
const resource = scannableSourcePath(module.resource);
|
|
10726
|
+
if (!resource) continue;
|
|
10727
|
+
const source = readProjectSource(resource);
|
|
10728
|
+
if (void 0 !== source) for (const api of candidates){
|
|
10729
|
+
if (firstOffenderByApi.has(api)) continue;
|
|
10730
|
+
const useRe = new RegExp(`\\b(?:chrome|browser)\\s*\\.\\s*${api}\\b`);
|
|
10731
|
+
if (!useRe.test(source)) continue;
|
|
10732
|
+
const files = emittedFilesOf(compilation, outer);
|
|
10733
|
+
if (!files || files.some((file)=>{
|
|
10734
|
+
const text = shippedText(file);
|
|
10735
|
+
return void 0 !== text && useRe.test(text);
|
|
10736
|
+
})) firstOffenderByApi.set(api, resource);
|
|
10737
|
+
}
|
|
10595
10738
|
}
|
|
10596
10739
|
if (firstOffenderByApi.size === candidates.length) break;
|
|
10597
10740
|
}
|
|
@@ -10672,13 +10815,13 @@ class ApplyDevDefaults {
|
|
|
10672
10815
|
...hostPermissionsPatch,
|
|
10673
10816
|
...patchBackground(canonicalManifest, this.browser),
|
|
10674
10817
|
...patchExternallyConnectable(canonicalManifest),
|
|
10675
|
-
|
|
10818
|
+
...patchWebResources(canonicalManifest)
|
|
10676
10819
|
};
|
|
10677
10820
|
try {
|
|
10678
10821
|
const declared = new Set(canonicalManifest.permissions || []);
|
|
10679
10822
|
const uses = findInjectedOnlyPermissionUses(compilation, declared, injectedPermissions);
|
|
10680
10823
|
for (const [api, file] of uses){
|
|
10681
|
-
const relative =
|
|
10824
|
+
const relative = __rspack_external_node_path_806ed179.relative(__rspack_external_node_path_806ed179.dirname(this.manifestPath), file);
|
|
10682
10825
|
const text = optionalPermissions.has(api) ? `manifest.json only lists the "${api}" permission under optional_permissions, but ${relative} uses chrome.${api}. It works in development only because the dev instrumentation injects "${api}" as required: the production build has it only after a runtime chrome.permissions.request, so guard the use or move "${api}" to permissions.` : partiallyGatedWarning(api, relative) || `manifest.json does not declare the "${api}" permission, but ${relative} uses chrome.${api}. It works in development only because the dev instrumentation injects "${api}": the production build will fail at runtime. Add "${api}" to permissions in manifest.json.`;
|
|
10683
10826
|
pushDevWarning('DevInjectedPermissionWarning', optionalPermissions.has(api) ? text + partiallyGatedNote(api) : text);
|
|
10684
10827
|
}
|
|
@@ -10687,7 +10830,7 @@ class ApplyDevDefaults {
|
|
|
10687
10830
|
const injectedOnlyHosts = findInjectedOnlyHostUses(compilation.modules, contentScriptMatches, declaredHostPatterns(canonicalManifest), optionalHostPatterns(canonicalManifest));
|
|
10688
10831
|
const hostKey = 3 === canonicalManifest.manifest_version ? 'host_permissions' : 'permissions';
|
|
10689
10832
|
for (const use of injectedOnlyHosts){
|
|
10690
|
-
const relative =
|
|
10833
|
+
const relative = __rspack_external_node_path_806ed179.relative(__rspack_external_node_path_806ed179.dirname(this.manifestPath), use.file);
|
|
10691
10834
|
const text = use.optional ? `manifest.json only lists "${use.pattern}" under optional host permissions, but ${relative} requests ${use.url}. It works in development only because a content script matches "${use.pattern}" and the dev build grants that host as required so it can re-inject the script on save. The production build has the host only after a runtime chrome.permissions.request, so guard the request or add "${use.pattern}" to ${hostKey} in manifest.json.` : `manifest.json does not grant host access to ${use.url}, but ${relative} requests it. The dev build grants that host because a content script matches "${use.pattern}" and it re-injects the script on save. The production build has no host permission for it, so the request is subject to the server's CORS policy and is blocked when the server does not allow it. If it needs the permission, add "${requestOriginPattern(use.url, use.pattern)}" to ${hostKey} in manifest.json rather than the content-script pattern.`;
|
|
10692
10835
|
pushDevWarning('DevInjectedHostWarning', text);
|
|
10693
10836
|
}
|
|
@@ -10912,6 +11055,17 @@ function collectContentScriptAsyncChunkFiles(compilation) {
|
|
|
10912
11055
|
});
|
|
10913
11056
|
return result;
|
|
10914
11057
|
}
|
|
11058
|
+
function collectPageContextEntryFiles(compilation) {
|
|
11059
|
+
const result = {};
|
|
11060
|
+
if ('function' != typeof compilation.entrypoints?.forEach) return result;
|
|
11061
|
+
compilation.entrypoints.forEach((entry, entryName)=>{
|
|
11062
|
+
if (!isPageContextEntry(String(entryName))) return;
|
|
11063
|
+
const files = new Set();
|
|
11064
|
+
for (const chunk of toFileArray(entry.chunks))for (const file of toFileArray(chunk.files))if (file.endsWith('.js')) files.add(unixify(file));
|
|
11065
|
+
if (files.size > 0) result[String(entryName)] = Array.from(files).sort();
|
|
11066
|
+
});
|
|
11067
|
+
return result;
|
|
11068
|
+
}
|
|
10915
11069
|
function collectContentScriptEntryImports(compilation, includeList) {
|
|
10916
11070
|
const entryImports = {};
|
|
10917
11071
|
const contentEntryNames = new Set(Object.keys(includeList || {}).filter((k)=>isPageContextEntry(k)));
|
|
@@ -10982,18 +11136,6 @@ function collectContentScriptEntryImports(compilation, includeList) {
|
|
|
10982
11136
|
}
|
|
10983
11137
|
return entryImports;
|
|
10984
11138
|
}
|
|
10985
|
-
function cleanMatches(matches) {
|
|
10986
|
-
return matches.map((match)=>{
|
|
10987
|
-
try {
|
|
10988
|
-
const url = new URL(match.replace(/^\*:\/\//, 'https://'));
|
|
10989
|
-
if (match.endsWith(url.pathname)) return `${match.substring(0, match.length - url.pathname.length)}/*`;
|
|
10990
|
-
if ('/' === url.pathname) return `${match}/*`;
|
|
10991
|
-
return match;
|
|
10992
|
-
} catch {
|
|
10993
|
-
return match;
|
|
10994
|
-
}
|
|
10995
|
-
});
|
|
10996
|
-
}
|
|
10997
11139
|
function warFieldError(filePath, opts) {
|
|
10998
11140
|
const displayPath = opts?.overrideNotFoundPath || filePath;
|
|
10999
11141
|
const lines = [];
|
|
@@ -11036,6 +11178,14 @@ function warInvalidMatchPattern(pattern) {
|
|
|
11036
11178
|
lines.push(`Update the pattern in your ${pintor.blue('manifest.json')} file. See ${pintor.underline('https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources#manifest_declaration')} for the format.`);
|
|
11037
11179
|
return lines.join('\n');
|
|
11038
11180
|
}
|
|
11181
|
+
function warUnreachableResource(resource, entryName) {
|
|
11182
|
+
const lines = [];
|
|
11183
|
+
lines.push(`${pintor.underline(entryName)} asks the extension for ${pintor.blue(resource)}, but ${pintor.blue('web_accessible_resources')} does not list it.`);
|
|
11184
|
+
lines.push("The browser refuses it with a SecurityError because a content script reads extension files with the page's origin.");
|
|
11185
|
+
lines.push(`Add it to ${pintor.blue('web_accessible_resources')} in ${pintor.blue('manifest.json')}, scoped to the matches that need it.`);
|
|
11186
|
+
lines.push(`Learn more: ${pintor.underline('https://extension.js.org/docs/development/web-accessible-resources')}`);
|
|
11187
|
+
return lines.join('\n');
|
|
11188
|
+
}
|
|
11039
11189
|
function entryImportsSummary(entryCount, totalResources) {
|
|
11040
11190
|
return `${messaging_prefix('debug')} war entryImports entries=${String(entryCount)} resources=${String(totalResources)}`;
|
|
11041
11191
|
}
|
|
@@ -11279,6 +11429,54 @@ function resolveUserDeclaredWAR(compilation, manifestPath, manifest, browser) {
|
|
|
11279
11429
|
v3
|
|
11280
11430
|
};
|
|
11281
11431
|
}
|
|
11432
|
+
function normalizeResourcePath(value) {
|
|
11433
|
+
return String(value || '').replace(/\\/g, '/').replace(/^\.\//, '').replace(/^\/+/, '');
|
|
11434
|
+
}
|
|
11435
|
+
function escapeRegex(value) {
|
|
11436
|
+
return value.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
|
11437
|
+
}
|
|
11438
|
+
function globToRegex(pattern) {
|
|
11439
|
+
const escaped = pattern.split('*').map((segment)=>escapeRegex(segment)).join('.*');
|
|
11440
|
+
return new RegExp(`^${escaped}$`);
|
|
11441
|
+
}
|
|
11442
|
+
function isResourceCovered(declared, candidate) {
|
|
11443
|
+
const target = normalizeResourcePath(candidate);
|
|
11444
|
+
for (const entry of declared){
|
|
11445
|
+
const pattern = normalizeResourcePath(entry);
|
|
11446
|
+
if (pattern === target) return true;
|
|
11447
|
+
if (pattern.includes('*')) try {
|
|
11448
|
+
if (globToRegex(pattern).test(target)) return true;
|
|
11449
|
+
} catch {}
|
|
11450
|
+
}
|
|
11451
|
+
return false;
|
|
11452
|
+
}
|
|
11453
|
+
const GET_URL_LITERAL_PATTERN = /getURL\s*\(\s*["'`]([^"'`\n)]+)["'`]\s*\)/g;
|
|
11454
|
+
const MAX_SCANNED_SOURCE_BYTES = 4194304;
|
|
11455
|
+
function collectGetUrlLiterals(source) {
|
|
11456
|
+
if (!source || source.length > MAX_SCANNED_SOURCE_BYTES) return [];
|
|
11457
|
+
const found = new Set();
|
|
11458
|
+
const pattern = new RegExp(GET_URL_LITERAL_PATTERN.source, 'g');
|
|
11459
|
+
let match = pattern.exec(source);
|
|
11460
|
+
while(match){
|
|
11461
|
+
const name = normalizeResourcePath(match[1]);
|
|
11462
|
+
if (name && !name.includes('${')) found.add(name);
|
|
11463
|
+
match = pattern.exec(source);
|
|
11464
|
+
}
|
|
11465
|
+
return Array.from(found).sort();
|
|
11466
|
+
}
|
|
11467
|
+
const TOOLING_RESOURCES = new Set([
|
|
11468
|
+
'manifest.json',
|
|
11469
|
+
'extension-js-control.json'
|
|
11470
|
+
]);
|
|
11471
|
+
function findUnreachableRuntimeResources(options) {
|
|
11472
|
+
const emitted = new Set(options.emittedAssetNames.map((name)=>normalizeResourcePath(name)));
|
|
11473
|
+
return collectGetUrlLiterals(options.source).filter((name)=>{
|
|
11474
|
+
if (TOOLING_RESOURCES.has(name)) return false;
|
|
11475
|
+
if (name.startsWith('hot/')) return false;
|
|
11476
|
+
if (!emitted.has(name)) return false;
|
|
11477
|
+
return !isResourceCovered(options.declaredResources, name);
|
|
11478
|
+
});
|
|
11479
|
+
}
|
|
11282
11480
|
function generate_manifest_getAssetSource(compilation, filename) {
|
|
11283
11481
|
const byGet = 'function' == typeof compilation.getAsset ? compilation.getAsset(filename) : void 0;
|
|
11284
11482
|
const byAssets = !byGet && compilation.assets ? compilation.assets[filename] : void 0;
|
|
@@ -11306,16 +11504,16 @@ function generate_manifest_getAssetSource(compilation, filename) {
|
|
|
11306
11504
|
function hasWildcardPattern(pattern) {
|
|
11307
11505
|
return /[*?[\]]/.test(pattern);
|
|
11308
11506
|
}
|
|
11309
|
-
function
|
|
11507
|
+
function generate_manifest_escapeRegex(s) {
|
|
11310
11508
|
return s.replace(/[.+^${}()|\\]/g, '\\$&');
|
|
11311
11509
|
}
|
|
11312
|
-
function
|
|
11313
|
-
const escaped = pattern.split('*').map((seg)=>
|
|
11510
|
+
function generate_manifest_globToRegex(pattern) {
|
|
11511
|
+
const escaped = pattern.split('*').map((seg)=>generate_manifest_escapeRegex(seg)).join('.*');
|
|
11314
11512
|
return new RegExp(`^${escaped}$`);
|
|
11315
11513
|
}
|
|
11316
11514
|
function isCoveredByExistingGlobs(existingPatterns, candidate) {
|
|
11317
11515
|
for (const existingPattern of existingPatterns)if (hasWildcardPattern(existingPattern)) try {
|
|
11318
|
-
const re =
|
|
11516
|
+
const re = generate_manifest_globToRegex(existingPattern);
|
|
11319
11517
|
if (re.test(candidate)) return true;
|
|
11320
11518
|
} catch {}
|
|
11321
11519
|
return false;
|
|
@@ -11356,6 +11554,42 @@ function toCanonicalContentScriptCss(jsFile) {
|
|
|
11356
11554
|
if (!/^content_scripts\/content-\d+\.js$/.test(normalized)) return;
|
|
11357
11555
|
return normalized.replace(/\.js$/, '.css');
|
|
11358
11556
|
}
|
|
11557
|
+
function declaredWarResources(manifest) {
|
|
11558
|
+
const war = manifest.web_accessible_resources;
|
|
11559
|
+
if (!Array.isArray(war)) return [];
|
|
11560
|
+
return war.flatMap((entry)=>{
|
|
11561
|
+
if ('string' == typeof entry) return [
|
|
11562
|
+
entry
|
|
11563
|
+
];
|
|
11564
|
+
const resources = entry.resources;
|
|
11565
|
+
return Array.isArray(resources) ? resources.map((r)=>String(r)) : [];
|
|
11566
|
+
});
|
|
11567
|
+
}
|
|
11568
|
+
function warnOnUnreachableResources(compilation, manifest) {
|
|
11569
|
+
try {
|
|
11570
|
+
const declared = declaredWarResources(manifest);
|
|
11571
|
+
const emittedAssetNames = listEmittedAssetNames(compilation);
|
|
11572
|
+
const entryFiles = collectPageContextEntryFiles(compilation);
|
|
11573
|
+
const reported = new Set();
|
|
11574
|
+
for (const [entryName, files] of Object.entries(entryFiles))for (const file of files){
|
|
11575
|
+
const unreachable = findUnreachableRuntimeResources({
|
|
11576
|
+
source: generate_manifest_getAssetSource(compilation, file),
|
|
11577
|
+
emittedAssetNames,
|
|
11578
|
+
declaredResources: declared
|
|
11579
|
+
});
|
|
11580
|
+
for (const resource of unreachable){
|
|
11581
|
+
const key = `${entryName}:${resource}`;
|
|
11582
|
+
if (reported.has(key)) continue;
|
|
11583
|
+
reported.add(key);
|
|
11584
|
+
compilation.warnings = compilation.warnings || [];
|
|
11585
|
+
const warning = new core_WebpackError(warUnreachableResource(resource, entryName));
|
|
11586
|
+
warning.name = 'UnreachableWebAccessibleResourceWarning';
|
|
11587
|
+
warning.file = file;
|
|
11588
|
+
compilation.warnings.push(warning);
|
|
11589
|
+
}
|
|
11590
|
+
}
|
|
11591
|
+
} catch {}
|
|
11592
|
+
}
|
|
11359
11593
|
function generateManifestPatches(compilation, manifestPath, entryImports, browser) {
|
|
11360
11594
|
const canonicalManifest = getManifestContent(compilation, manifestPath);
|
|
11361
11595
|
const resolved = resolveUserDeclaredWAR(compilation, manifestPath, canonicalManifest, browser);
|
|
@@ -11495,6 +11729,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
|
|
|
11495
11729
|
matches: Array.from(new Set(entry.matches)).sort()
|
|
11496
11730
|
})).sort((a, b)=>a.matches.join(',').localeCompare(b.matches.join(',')));
|
|
11497
11731
|
} else if (webAccessibleResourcesV2.length > 0) canonicalManifest.web_accessible_resources = Array.from(new Set(webAccessibleResourcesV2)).sort();
|
|
11732
|
+
warnOnUnreachableResources(compilation, canonicalManifest);
|
|
11498
11733
|
const source = JSON.stringify(canonicalManifest, null, 2);
|
|
11499
11734
|
const rawSource = new core_sources.RawSource(source);
|
|
11500
11735
|
setCurrentManifestContent(compilation, source);
|
|
@@ -11674,6 +11909,22 @@ class PersistManifestToDisk {
|
|
|
11674
11909
|
});
|
|
11675
11910
|
}
|
|
11676
11911
|
}
|
|
11912
|
+
function dropEdgeStoreKey(manifest, browser) {
|
|
11913
|
+
if ('edge' !== String(browser)) return {
|
|
11914
|
+
manifest,
|
|
11915
|
+
dropped: false
|
|
11916
|
+
};
|
|
11917
|
+
const source = manifest;
|
|
11918
|
+
if (!('key' in source)) return {
|
|
11919
|
+
manifest,
|
|
11920
|
+
dropped: false
|
|
11921
|
+
};
|
|
11922
|
+
const { key: _key, ...rest } = source;
|
|
11923
|
+
return {
|
|
11924
|
+
manifest: rest,
|
|
11925
|
+
dropped: true
|
|
11926
|
+
};
|
|
11927
|
+
}
|
|
11677
11928
|
function gecko_data_collection_missingGeckoDataCollectionPermissions(manifest) {
|
|
11678
11929
|
const bss = manifest.browser_specific_settings;
|
|
11679
11930
|
const declaration = bss?.gecko?.data_collection_permissions;
|
|
@@ -12784,7 +13035,134 @@ function patchGeckoBackground(manifest, browser) {
|
|
|
12784
13035
|
}
|
|
12785
13036
|
};
|
|
12786
13037
|
}
|
|
12787
|
-
|
|
13038
|
+
const webkitUnsupportedApis = {
|
|
13039
|
+
sidePanel: safariSidePanelUnsupported,
|
|
13040
|
+
offscreen: safariOffscreenUnsupported,
|
|
13041
|
+
tabGroups: safariTabGroupsUnsupported,
|
|
13042
|
+
management: safariManagementUnsupported,
|
|
13043
|
+
userScripts: safariUserScriptsUnsupported,
|
|
13044
|
+
identity: safariIdentityUnsupported,
|
|
13045
|
+
notifications: safariNotificationsUnsupported,
|
|
13046
|
+
omnibox: safariOmniboxUnsupported,
|
|
13047
|
+
bookmarks: safariBookmarksUnsupported,
|
|
13048
|
+
history: safariHistoryUnsupported,
|
|
13049
|
+
downloads: safariDownloadsUnsupported,
|
|
13050
|
+
idle: safariIdleUnsupported
|
|
13051
|
+
};
|
|
13052
|
+
const webkitUnsupportedMembers = [
|
|
13053
|
+
{
|
|
13054
|
+
api: 'action',
|
|
13055
|
+
member: 'getUserSettings',
|
|
13056
|
+
kind: 'call'
|
|
13057
|
+
},
|
|
13058
|
+
{
|
|
13059
|
+
api: 'action',
|
|
13060
|
+
member: 'getBadgeTextColor',
|
|
13061
|
+
kind: 'call'
|
|
13062
|
+
},
|
|
13063
|
+
{
|
|
13064
|
+
api: 'action',
|
|
13065
|
+
member: 'setBadgeTextColor',
|
|
13066
|
+
kind: 'call'
|
|
13067
|
+
},
|
|
13068
|
+
{
|
|
13069
|
+
api: 'action',
|
|
13070
|
+
member: 'onUserSettingsChanged',
|
|
13071
|
+
kind: 'read'
|
|
13072
|
+
},
|
|
13073
|
+
{
|
|
13074
|
+
api: 'storage',
|
|
13075
|
+
member: 'managed',
|
|
13076
|
+
kind: 'read'
|
|
13077
|
+
},
|
|
13078
|
+
{
|
|
13079
|
+
api: 'runtime',
|
|
13080
|
+
member: 'getContexts',
|
|
13081
|
+
kind: 'call'
|
|
13082
|
+
},
|
|
13083
|
+
{
|
|
13084
|
+
api: 'runtime',
|
|
13085
|
+
member: 'onSuspend',
|
|
13086
|
+
kind: 'read'
|
|
13087
|
+
},
|
|
13088
|
+
{
|
|
13089
|
+
api: 'runtime',
|
|
13090
|
+
member: 'onSuspendCanceled',
|
|
13091
|
+
kind: 'read'
|
|
13092
|
+
},
|
|
13093
|
+
{
|
|
13094
|
+
api: 'runtime',
|
|
13095
|
+
member: 'onUpdateAvailable',
|
|
13096
|
+
kind: 'read'
|
|
13097
|
+
},
|
|
13098
|
+
{
|
|
13099
|
+
api: 'declarativeNetRequest',
|
|
13100
|
+
member: 'getAvailableStaticRuleCount',
|
|
13101
|
+
kind: 'call'
|
|
13102
|
+
},
|
|
13103
|
+
{
|
|
13104
|
+
api: 'declarativeNetRequest',
|
|
13105
|
+
member: 'getDisabledRuleIds',
|
|
13106
|
+
kind: 'call'
|
|
13107
|
+
},
|
|
13108
|
+
{
|
|
13109
|
+
api: 'declarativeNetRequest',
|
|
13110
|
+
member: 'updateStaticRules',
|
|
13111
|
+
kind: 'call'
|
|
13112
|
+
},
|
|
13113
|
+
{
|
|
13114
|
+
api: 'declarativeNetRequest',
|
|
13115
|
+
member: 'testMatchOutcome',
|
|
13116
|
+
kind: 'call'
|
|
13117
|
+
},
|
|
13118
|
+
{
|
|
13119
|
+
api: 'declarativeNetRequest',
|
|
13120
|
+
member: 'onRuleMatchedDebug',
|
|
13121
|
+
kind: 'read'
|
|
13122
|
+
},
|
|
13123
|
+
{
|
|
13124
|
+
api: 'tabs',
|
|
13125
|
+
member: 'group',
|
|
13126
|
+
kind: 'call'
|
|
13127
|
+
},
|
|
13128
|
+
{
|
|
13129
|
+
api: 'tabs',
|
|
13130
|
+
member: 'ungroup',
|
|
13131
|
+
kind: 'call'
|
|
13132
|
+
},
|
|
13133
|
+
{
|
|
13134
|
+
api: 'webNavigation',
|
|
13135
|
+
member: 'onCreatedNavigationTarget',
|
|
13136
|
+
kind: 'read'
|
|
13137
|
+
},
|
|
13138
|
+
{
|
|
13139
|
+
api: 'webNavigation',
|
|
13140
|
+
member: 'onHistoryStateUpdated',
|
|
13141
|
+
kind: 'read'
|
|
13142
|
+
},
|
|
13143
|
+
{
|
|
13144
|
+
api: 'webNavigation',
|
|
13145
|
+
member: 'onReferenceFragmentUpdated',
|
|
13146
|
+
kind: 'read'
|
|
13147
|
+
},
|
|
13148
|
+
{
|
|
13149
|
+
api: 'webNavigation',
|
|
13150
|
+
member: 'onTabReplaced',
|
|
13151
|
+
kind: 'read'
|
|
13152
|
+
},
|
|
13153
|
+
{
|
|
13154
|
+
api: 'windows',
|
|
13155
|
+
member: 'onBoundsChanged',
|
|
13156
|
+
kind: 'read'
|
|
13157
|
+
}
|
|
13158
|
+
];
|
|
13159
|
+
const webkitMemberEntries = webkitUnsupportedMembers.filter((entry)=>!(entry.api in webkitUnsupportedApis));
|
|
13160
|
+
const webkitMemberByKey = new Map(webkitUnsupportedMembers.map((entry)=>[
|
|
13161
|
+
`${entry.api}.${entry.member}`,
|
|
13162
|
+
entry
|
|
13163
|
+
]));
|
|
13164
|
+
function geckoUnsupportedApis(manifestVersion, engine = 'gecko') {
|
|
13165
|
+
if ('webkit' === engine) return Object.keys(webkitUnsupportedApis);
|
|
12788
13166
|
return 2 === manifestVersion ? [
|
|
12789
13167
|
'sidePanel',
|
|
12790
13168
|
'action'
|
|
@@ -12792,52 +13170,51 @@ function geckoUnsupportedApis(manifestVersion) {
|
|
|
12792
13170
|
'sidePanel'
|
|
12793
13171
|
];
|
|
12794
13172
|
}
|
|
12795
|
-
function usesGeckoUnsupportedApi(source, api) {
|
|
12796
|
-
const
|
|
13173
|
+
function usesGeckoUnsupportedApi(source, api, engine = 'gecko') {
|
|
13174
|
+
const chain = 'webkit' === engine ? '' : '\\??';
|
|
13175
|
+
const memberRe = new RegExp(`\\b(?:chrome|browser)\\s*\\.\\s*${api}\\s*${chain}\\.\\s*[A-Za-z_$]`);
|
|
12797
13176
|
return memberRe.test(source);
|
|
12798
13177
|
}
|
|
12799
|
-
|
|
12800
|
-
const
|
|
12801
|
-
const
|
|
12802
|
-
|
|
12803
|
-
const scripts = new Map();
|
|
12804
|
-
let assets;
|
|
12805
|
-
try {
|
|
12806
|
-
assets = compilation.getAssets?.() || [];
|
|
12807
|
-
} catch {
|
|
12808
|
-
return scripts;
|
|
12809
|
-
}
|
|
12810
|
-
for (const asset of assets)if (EMITTED_SCRIPT_RE.test(asset.name)) try {
|
|
12811
|
-
const raw = asset.source.source();
|
|
12812
|
-
const text = 'string' == typeof raw ? raw : raw.toString('utf-8');
|
|
12813
|
-
if (text.length > MAX_ASSET_BYTES) continue;
|
|
12814
|
-
scripts.set(asset.name, text);
|
|
12815
|
-
} catch {}
|
|
12816
|
-
return scripts;
|
|
12817
|
-
}
|
|
12818
|
-
function readProjectSource(resource) {
|
|
12819
|
-
try {
|
|
12820
|
-
if (__rspack_external_node_fs_1b05aee1.statSync(resource).size > MAX_SOURCE_BYTES) return;
|
|
12821
|
-
return __rspack_external_node_fs_1b05aee1.readFileSync(resource, 'utf-8');
|
|
12822
|
-
} catch {
|
|
12823
|
-
return;
|
|
12824
|
-
}
|
|
13178
|
+
function usesWebkitUnsupportedMember(source, entry) {
|
|
13179
|
+
const tail = 'call' === entry.kind ? '\\s*\\(' : '\\s*\\.\\s*[A-Za-z_$]';
|
|
13180
|
+
const memberRe = new RegExp(`\\b(?:chrome|browser)\\s*\\.\\s*${entry.api}\\s*\\.\\s*${entry.member}(?![\\w$])${tail}`);
|
|
13181
|
+
return memberRe.test(source);
|
|
12825
13182
|
}
|
|
12826
|
-
function
|
|
12827
|
-
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
13183
|
+
function scanTargets(manifestVersion, engine) {
|
|
13184
|
+
const targets = geckoUnsupportedApis(manifestVersion, engine).map((api)=>({
|
|
13185
|
+
key: api,
|
|
13186
|
+
api,
|
|
13187
|
+
test: (text)=>usesGeckoUnsupportedApi(text, api, engine)
|
|
13188
|
+
}));
|
|
13189
|
+
if ('webkit' !== engine) return targets;
|
|
13190
|
+
for (const entry of webkitMemberEntries)targets.push({
|
|
13191
|
+
key: `${entry.api}.${entry.member}`,
|
|
13192
|
+
api: entry.api,
|
|
13193
|
+
member: entry.member,
|
|
13194
|
+
test: (text)=>usesWebkitUnsupportedMember(text, entry)
|
|
13195
|
+
});
|
|
13196
|
+
return targets;
|
|
12835
13197
|
}
|
|
12836
|
-
function findGeckoUnsupportedApiUses(compilation, manifestVersion) {
|
|
12837
|
-
const
|
|
13198
|
+
function findGeckoUnsupportedApiUses(compilation, manifestVersion, engine = 'gecko', requireEmittedEvidence = false) {
|
|
13199
|
+
const targets = scanTargets(manifestVersion, engine);
|
|
12838
13200
|
const emitted = readEmittedScripts(compilation);
|
|
12839
13201
|
const explained = new Set();
|
|
12840
13202
|
const uses = new Map();
|
|
13203
|
+
const shipped = new Map();
|
|
13204
|
+
const shippedText = (file)=>{
|
|
13205
|
+
if (shipped.has(file)) return shipped.get(file);
|
|
13206
|
+
const text = emitted.get(file);
|
|
13207
|
+
if (void 0 === text) return;
|
|
13208
|
+
const compressed = requireEmittedEvidence ? shippableText(text) : text;
|
|
13209
|
+
shipped.set(file, compressed);
|
|
13210
|
+
return compressed;
|
|
13211
|
+
};
|
|
13212
|
+
const carries = (file, target)=>{
|
|
13213
|
+
const raw = emitted.get(file);
|
|
13214
|
+
if (void 0 === raw || !target.test(raw)) return false;
|
|
13215
|
+
const text = shippedText(file);
|
|
13216
|
+
return void 0 !== text && target.test(text);
|
|
13217
|
+
};
|
|
12841
13218
|
for (const outer of compilation.modules){
|
|
12842
13219
|
const inner = outer.modules ? [
|
|
12843
13220
|
...outer.modules
|
|
@@ -12848,20 +13225,20 @@ function findGeckoUnsupportedApiUses(compilation, manifestVersion) {
|
|
|
12848
13225
|
const resource = scannableSourcePath(module.resource);
|
|
12849
13226
|
if (!resource) continue;
|
|
12850
13227
|
const source = readProjectSource(resource);
|
|
12851
|
-
if (void 0 !== source) for (const
|
|
12852
|
-
const key = `${
|
|
12853
|
-
if (uses.has(key) || !
|
|
13228
|
+
if (void 0 !== source) for (const target of targets){
|
|
13229
|
+
const key = `${target.key}\0${resource}`;
|
|
13230
|
+
if (uses.has(key) || !target.test(source)) continue;
|
|
12854
13231
|
const files = emittedFilesOf(compilation, outer);
|
|
12855
13232
|
if (files) {
|
|
12856
|
-
const carrying = files.filter((file)=>
|
|
12857
|
-
const text = emitted.get(file);
|
|
12858
|
-
return void 0 !== text && usesGeckoUnsupportedApi(text, api);
|
|
12859
|
-
});
|
|
13233
|
+
const carrying = files.filter((file)=>carries(file, target));
|
|
12860
13234
|
if (!carrying.length) continue;
|
|
12861
|
-
for (const file of carrying)explained.add(`${
|
|
12862
|
-
}
|
|
13235
|
+
for (const file of carrying)explained.add(`${target.key}\0${file}`);
|
|
13236
|
+
} else if (requireEmittedEvidence) continue;
|
|
12863
13237
|
uses.set(key, {
|
|
12864
|
-
api,
|
|
13238
|
+
api: target.api,
|
|
13239
|
+
...target.member ? {
|
|
13240
|
+
member: target.member
|
|
13241
|
+
} : {},
|
|
12865
13242
|
file: resource,
|
|
12866
13243
|
emitted: false
|
|
12867
13244
|
});
|
|
@@ -12871,10 +13248,13 @@ function findGeckoUnsupportedApiUses(compilation, manifestVersion) {
|
|
|
12871
13248
|
if (!compilation.chunkGraph) return [
|
|
12872
13249
|
...uses.values()
|
|
12873
13250
|
];
|
|
12874
|
-
for (const
|
|
12875
|
-
const key = `${
|
|
12876
|
-
if (!explained.has(key) &&
|
|
12877
|
-
api,
|
|
13251
|
+
for (const name of emitted.keys())for (const target of targets){
|
|
13252
|
+
const key = `${target.key}\0${name}`;
|
|
13253
|
+
if (!explained.has(key) && carries(name, target)) uses.set(key, {
|
|
13254
|
+
api: target.api,
|
|
13255
|
+
...target.member ? {
|
|
13256
|
+
member: target.member
|
|
13257
|
+
} : {},
|
|
12878
13258
|
file: name,
|
|
12879
13259
|
emitted: true
|
|
12880
13260
|
});
|
|
@@ -12896,16 +13276,25 @@ function relativeToProject(projectPath, file) {
|
|
|
12896
13276
|
}
|
|
12897
13277
|
return __rspack_external_node_path_806ed179.relative(projectPath, file) || file;
|
|
12898
13278
|
}
|
|
12899
|
-
function reportGeckoUnsupportedApis(compilation, compiler, browser, manifest, projectPath) {
|
|
12900
|
-
|
|
12901
|
-
if (!
|
|
13279
|
+
function reportGeckoUnsupportedApis(compilation, compiler, browser, manifest, projectPath, reported) {
|
|
13280
|
+
const engine = isGeckoBasedBrowser(String(browser)) ? 'gecko' : isWebkitBasedBrowser(String(browser)) ? 'webkit' : void 0;
|
|
13281
|
+
if (!engine) return;
|
|
13282
|
+
const isProduction = 'production' === compiler.options.mode;
|
|
13283
|
+
if (!isProduction && 'webkit' !== engine) return;
|
|
12902
13284
|
try {
|
|
12903
|
-
const uses = findGeckoUnsupportedApiUses(compilation, manifest.manifest_version);
|
|
13285
|
+
const uses = findGeckoUnsupportedApiUses(compilation, manifest.manifest_version, engine, !isProduction);
|
|
12904
13286
|
for (const use of uses){
|
|
12905
13287
|
const label = use.emitted ? use.file : relativeToProject(projectPath, use.file);
|
|
12906
|
-
|
|
13288
|
+
if (!isProduction && reported) {
|
|
13289
|
+
const signature = `${use.api}.${use.member || ''}\0${label}`;
|
|
13290
|
+
if (reported.has(signature)) continue;
|
|
13291
|
+
reported.add(signature);
|
|
13292
|
+
}
|
|
13293
|
+
const memberEntry = use.member ? webkitMemberByKey.get(`${use.api}.${use.member}`) : void 0;
|
|
13294
|
+
const webkitMessage = 'webkit' !== engine || memberEntry ? void 0 : webkitUnsupportedApis[use.api];
|
|
13295
|
+
const text = memberEntry ? safariMemberUnsupported(label, memberEntry.api, memberEntry.member, memberEntry.kind) : webkitMessage ? webkitMessage(label) : 'sidePanel' === use.api ? geckoSidePanelUnsupported(label) : geckoActionUnsupportedOnMv2(label);
|
|
12907
13296
|
const warn = new core_WebpackError(text);
|
|
12908
|
-
warn.name = 'GeckoUnsupportedApiWarning';
|
|
13297
|
+
warn.name = 'webkit' === engine ? 'SafariUnsupportedApiWarning' : 'GeckoUnsupportedApiWarning';
|
|
12909
13298
|
warn.file = label;
|
|
12910
13299
|
compilation.warnings.push(warn);
|
|
12911
13300
|
}
|
|
@@ -12915,6 +13304,7 @@ class UpdateManifest {
|
|
|
12915
13304
|
manifestPath;
|
|
12916
13305
|
browser;
|
|
12917
13306
|
reportedFatalFixes = new Set();
|
|
13307
|
+
reportedUnsupportedApis = new Set();
|
|
12918
13308
|
constructor(options){
|
|
12919
13309
|
this.manifestPath = options.manifestPath;
|
|
12920
13310
|
this.browser = options.browser || 'chrome';
|
|
@@ -12946,10 +13336,19 @@ class UpdateManifest {
|
|
|
12946
13336
|
if (dropReason) reportToCompilation(compilation, compiler, 'conflicts' === dropReason ? pageActionDroppedForBrowserAction(String(this.browser)) : pageActionNotSupportedByBrowser(String(this.browser)), 'warning', 'manifest.json');
|
|
12947
13337
|
if (hasMv2SandboxPolicy(forBrowser)) reportToCompilation(compilation, compiler, mv2SandboxPolicyDropped(String(this.browser)), 'warning', 'manifest.json');
|
|
12948
13338
|
for (const dropped of findDroppedVendorKeys(manifest, this.browser))if (dropped.appliedBefore) reportToCompilation(compilation, compiler, vendorPrefixedKeyDropped(dropped.path, dropped.familyPath, dropped.vendor, String(this.browser)), 'warning', 'manifest.json');
|
|
13339
|
+
if (!isValidManifestVersion(forBrowser.manifest_version)) reportToCompilation(compilation, compiler, manifestVersionLostForBrowser(String(this.browser), findPrefixedManifestVersionKeys(manifest), forBrowser.manifest_version), 'error', 'manifest.json');
|
|
12949
13340
|
const projectPath = compiler.options.context || __rspack_external_node_path_806ed179.dirname(this.manifestPath);
|
|
12950
13341
|
let patchedManifest = buildCanonicalManifest(this.manifestPath, manifest, this.browser, projectPath);
|
|
13342
|
+
if ('production' === compiler.options.mode) {
|
|
13343
|
+
const edgeKey = dropEdgeStoreKey(patchedManifest, this.browser);
|
|
13344
|
+
if (edgeKey.dropped) {
|
|
13345
|
+
patchedManifest = edgeKey.manifest;
|
|
13346
|
+
reportToCompilation(compilation, compiler, edgeStoreKeyDropped(String(this.browser)), 'warning', 'manifest.json');
|
|
13347
|
+
}
|
|
13348
|
+
}
|
|
12951
13349
|
patchedManifest = patchGeckoBackground(patchedManifest, this.browser);
|
|
12952
13350
|
patchedManifest = patchChromiumBackground(patchedManifest, this.browser);
|
|
13351
|
+
patchedManifest = patchWebkitBackground(patchedManifest, this.browser);
|
|
12953
13352
|
patchedManifest = patchChromiumThemeColors(patchedManifest, this.browser);
|
|
12954
13353
|
const overrides = getManifestOverrides(this.manifestPath, manifest, projectPath);
|
|
12955
13354
|
if ('development' === compiler.options.mode) {
|
|
@@ -12989,7 +13388,7 @@ class UpdateManifest {
|
|
|
12989
13388
|
warn.file = 'manifest.json';
|
|
12990
13389
|
compilation.warnings.push(warn);
|
|
12991
13390
|
}
|
|
12992
|
-
reportGeckoUnsupportedApis(compilation, compiler, this.browser, patchedManifest, projectPath);
|
|
13391
|
+
reportGeckoUnsupportedApis(compilation, compiler, this.browser, patchedManifest, projectPath, this.reportedUnsupportedApis);
|
|
12993
13392
|
const source = JSON.stringify(patchedManifest, null, 2);
|
|
12994
13393
|
const rawSource = new core_sources.RawSource(source);
|
|
12995
13394
|
setCurrentManifestContent(compilation, source);
|
|
@@ -13496,6 +13895,100 @@ function parsesAsModule(source) {
|
|
|
13496
13895
|
return false;
|
|
13497
13896
|
}
|
|
13498
13897
|
}
|
|
13898
|
+
const WORKER_FROM_URL = /new\s+Worker\s*\(\s*(?:\/\*[\s\S]*?\*\/\s*)?new\s+URL\s*\(/;
|
|
13899
|
+
const EXTENSION_BASES = [
|
|
13900
|
+
/^import\.meta\.url$/,
|
|
13901
|
+
/^[A-Za-z_$][\w$]*\.b$/,
|
|
13902
|
+
/^(?:chrome|browser)\.runtime\.getURL\(/,
|
|
13903
|
+
/^["'`](?:chrome-extension|moz-extension|safari-web-extension):\/\//
|
|
13904
|
+
];
|
|
13905
|
+
const JS_ASSET = /\.m?js$/i;
|
|
13906
|
+
function readCallArguments(source, from) {
|
|
13907
|
+
const args = [];
|
|
13908
|
+
let depth = 0;
|
|
13909
|
+
let start = from;
|
|
13910
|
+
for(let i = from; i < source.length; i++){
|
|
13911
|
+
const char = source[i];
|
|
13912
|
+
if ('"' === char || "'" === char || '`' === char) {
|
|
13913
|
+
i = skipQuoted(source, i, char);
|
|
13914
|
+
continue;
|
|
13915
|
+
}
|
|
13916
|
+
if ('/' === char && '*' === source[i + 1]) {
|
|
13917
|
+
const end = source.indexOf('*/', i + 2);
|
|
13918
|
+
i = -1 === end ? source.length : end + 1;
|
|
13919
|
+
continue;
|
|
13920
|
+
}
|
|
13921
|
+
if ('/' === char && '/' === source[i + 1]) {
|
|
13922
|
+
const end = source.indexOf('\n', i + 2);
|
|
13923
|
+
i = -1 === end ? source.length : end;
|
|
13924
|
+
continue;
|
|
13925
|
+
}
|
|
13926
|
+
if ('(' === char || '[' === char || '{' === char) {
|
|
13927
|
+
depth++;
|
|
13928
|
+
continue;
|
|
13929
|
+
}
|
|
13930
|
+
if (')' === char || ']' === char || '}' === char) {
|
|
13931
|
+
if (0 === depth) {
|
|
13932
|
+
args.push(source.slice(start, i));
|
|
13933
|
+
return args;
|
|
13934
|
+
}
|
|
13935
|
+
depth--;
|
|
13936
|
+
continue;
|
|
13937
|
+
}
|
|
13938
|
+
if (',' === char && 0 === depth) {
|
|
13939
|
+
args.push(source.slice(start, i));
|
|
13940
|
+
start = i + 1;
|
|
13941
|
+
}
|
|
13942
|
+
}
|
|
13943
|
+
}
|
|
13944
|
+
function skipQuoted(source, from, quote) {
|
|
13945
|
+
for(let i = from + 1; i < source.length; i++){
|
|
13946
|
+
if ('\\' === source[i]) {
|
|
13947
|
+
i++;
|
|
13948
|
+
continue;
|
|
13949
|
+
}
|
|
13950
|
+
if (source[i] === quote) return i;
|
|
13951
|
+
}
|
|
13952
|
+
return source.length;
|
|
13953
|
+
}
|
|
13954
|
+
function resolvesAgainstExtension(base) {
|
|
13955
|
+
const text = (base ?? '').replace(/\s+/g, '');
|
|
13956
|
+
if (!text) return true;
|
|
13957
|
+
return EXTENSION_BASES.some((shape)=>shape.test(text));
|
|
13958
|
+
}
|
|
13959
|
+
function startsWorkerFromExtensionUrl(source) {
|
|
13960
|
+
const call = new RegExp(WORKER_FROM_URL.source, 'g');
|
|
13961
|
+
let match = call.exec(source);
|
|
13962
|
+
while(match){
|
|
13963
|
+
const args = readCallArguments(source, match.index + match[0].length);
|
|
13964
|
+
if (args && resolvesAgainstExtension(args[1])) return true;
|
|
13965
|
+
match = call.exec(source);
|
|
13966
|
+
}
|
|
13967
|
+
return false;
|
|
13968
|
+
}
|
|
13969
|
+
class WarnPageContextWorker {
|
|
13970
|
+
apply(compiler) {
|
|
13971
|
+
if (!compiler?.hooks?.thisCompilation?.tap) return;
|
|
13972
|
+
compiler.hooks.thisCompilation.tap("scripts:warn-page-context-worker", (compilation)=>{
|
|
13973
|
+
compilation.hooks.processAssets.tap({
|
|
13974
|
+
name: "scripts:warn-page-context-worker",
|
|
13975
|
+
stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT
|
|
13976
|
+
}, ()=>{
|
|
13977
|
+
for (const asset of compilation.getAssets()){
|
|
13978
|
+
const name = String(asset.name || '');
|
|
13979
|
+
if (!JS_ASSET.test(name)) continue;
|
|
13980
|
+
const surface = classifyEntrySurface(name);
|
|
13981
|
+
if ("content_script" !== surface && "script" !== surface) continue;
|
|
13982
|
+
const source = String(asset.source?.source() || '');
|
|
13983
|
+
if (!startsWorkerFromExtensionUrl(source)) continue;
|
|
13984
|
+
const warning = new core_WebpackError(workerStartedFromPageContext(name, surface));
|
|
13985
|
+
warning.file = name;
|
|
13986
|
+
compilation.warnings.push(warning);
|
|
13987
|
+
}
|
|
13988
|
+
});
|
|
13989
|
+
});
|
|
13990
|
+
}
|
|
13991
|
+
}
|
|
13499
13992
|
class WarnSplitInitialChunks {
|
|
13500
13993
|
apply(compiler) {
|
|
13501
13994
|
if (!compiler?.hooks?.thisCompilation?.tap) return;
|
|
@@ -13552,6 +14045,7 @@ class ScriptsPlugin {
|
|
|
13552
14045
|
if ('production' === compiler.options.mode) new AddPublicPathRuntimeModule().apply(compiler);
|
|
13553
14046
|
new ValidateEmittedScriptSyntax().apply(compiler);
|
|
13554
14047
|
new WarnSplitInitialChunks().apply(compiler);
|
|
14048
|
+
new WarnPageContextWorker().apply(compiler);
|
|
13555
14049
|
}
|
|
13556
14050
|
}
|
|
13557
14051
|
class CollectContentEntryImports {
|
|
@@ -14350,6 +14844,12 @@ function webpackConfig(projectStructure, devOptions) {
|
|
|
14350
14844
|
optimization: {
|
|
14351
14845
|
emitOnErrors: false,
|
|
14352
14846
|
minimize: 'production' === devOptions.mode,
|
|
14847
|
+
minimizer: [
|
|
14848
|
+
new SwcJsMinimizerRspackPlugin(),
|
|
14849
|
+
new LightningCssMinimizerRspackPlugin({
|
|
14850
|
+
removeUnusedLocalIdents: false
|
|
14851
|
+
})
|
|
14852
|
+
],
|
|
14353
14853
|
sideEffects: true,
|
|
14354
14854
|
usedExports: 'global',
|
|
14355
14855
|
concatenateModules: 'production' === devOptions.mode,
|