extension-develop 4.1.18 → 4.1.20
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 +70 -14
- package/dist/832~0.mjs +26 -6
- package/dist/840~0.mjs +75 -6
- package/dist/938~0.mjs +1 -1
- package/dist/950~0.mjs +3 -2
- package/dist/command-preview.d.ts +0 -8
- 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/consumer-client.d.ts +0 -10
- package/dist/dev-server/control-bridge/contracts.d.ts +1 -43
- package/dist/dev-server/control-bridge/logs-file.d.ts +0 -1
- package/dist/dev-server/control-bridge/logs-query.d.ts +0 -16
- package/dist/dev-server/control-bridge/producer-runtime.d.ts +1 -2
- package/dist/dev-server/control-bridge/ws-control-server.d.ts +1 -0
- package/dist/dev-server~0.mjs +23 -6
- package/dist/extension-js-devtools/chrome/images/icon-128.png +0 -0
- package/dist/extension-js-devtools/chrome/images/icon-16.png +0 -0
- package/dist/extension-js-devtools/chrome/images/icon-32.png +0 -0
- package/dist/extension-js-devtools/chrome/images/icon-48.png +0 -0
- package/dist/extension-js-devtools/chrome/manifest.json +4 -1
- package/dist/extension-js-devtools/chrome/pages/welcome.css +1 -1
- package/dist/extension-js-devtools/chrome/pages/welcome.html +1 -1
- package/dist/extension-js-devtools/chrome/pages/welcome.js +2 -20
- package/dist/extension-js-devtools/chromium/images/icon-128.png +0 -0
- package/dist/extension-js-devtools/chromium/images/icon-16.png +0 -0
- package/dist/extension-js-devtools/chromium/images/icon-32.png +0 -0
- package/dist/extension-js-devtools/chromium/images/icon-48.png +0 -0
- package/dist/extension-js-devtools/chromium/manifest.json +4 -1
- package/dist/extension-js-devtools/chromium/pages/welcome.css +1 -1
- package/dist/extension-js-devtools/chromium/pages/welcome.html +1 -1
- package/dist/extension-js-devtools/chromium/pages/welcome.js +2 -20
- package/dist/extension-js-devtools/edge/images/icon-128.png +0 -0
- package/dist/extension-js-devtools/edge/images/icon-16.png +0 -0
- package/dist/extension-js-devtools/edge/images/icon-32.png +0 -0
- package/dist/extension-js-devtools/edge/images/icon-48.png +0 -0
- package/dist/extension-js-devtools/edge/manifest.json +4 -2
- package/dist/extension-js-devtools/edge/pages/welcome.css +1 -1
- package/dist/extension-js-devtools/edge/pages/welcome.html +1 -1
- package/dist/extension-js-devtools/edge/pages/welcome.js +2 -20
- package/dist/extension-js-devtools/firefox/images/icon-128.png +0 -0
- package/dist/extension-js-devtools/firefox/images/icon-16.png +0 -0
- package/dist/extension-js-devtools/firefox/images/icon-32.png +0 -0
- package/dist/extension-js-devtools/firefox/images/icon-48.png +0 -0
- package/dist/extension-js-devtools/firefox/manifest.json +4 -1
- package/dist/extension-js-devtools/firefox/pages/welcome.css +1 -1
- package/dist/extension-js-devtools/firefox/pages/welcome.html +1 -1
- package/dist/extension-js-devtools/firefox/pages/welcome.js +2 -20
- package/dist/lib/build-summary.d.ts +0 -11
- 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 +8 -0
- package/dist/lib/merge-options.d.ts +0 -40
- package/dist/lib/messages.d.ts +1 -1
- 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 -35
- 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 +1 -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-tools/vue.d.ts +1 -0
- package/dist/plugin-perf-budgets/index.d.ts +0 -21
- package/dist/plugin-playwright/index.d.ts +3 -2
- package/dist/plugin-reload/classify-reload.d.ts +0 -4
- package/dist/plugin-reload/index.d.ts +1 -19
- 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/folder-extensions/types.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/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 +117 -13
- package/dist/plugin-web-extension/feature-scripts/index.d.ts +0 -10
- package/dist/plugin-web-extension/feature-scripts/steps/native-geturl-import-loader.d.ts +0 -3
- 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/shared/discover-devtools-panels.d.ts +0 -6
- package/dist/plugin-web-extension/shared/paths.d.ts +0 -1
- package/dist/rspack-config~0.mjs +690 -139
- package/dist/types.d.ts +0 -190
- package/package.json +3 -2
- package/runtime/process-shim.cjs +2 -0
- package/dist/extension-js-devtools/chrome/images/logo.png +0 -0
- package/dist/extension-js-devtools/chrome/shared/framework.js +0 -1
- package/dist/extension-js-devtools/chromium/images/logo.png +0 -0
- package/dist/extension-js-devtools/chromium/shared/framework.js +0 -1
- package/dist/extension-js-devtools/edge/images/logo.png +0 -0
- package/dist/extension-js-devtools/edge/shared/framework.js +0 -1
- package/dist/extension-js-devtools/firefox/images/logo.png +0 -0
- package/dist/extension-js-devtools/firefox/shared/framework.js +0 -1
package/dist/rspack-config~0.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import { bundlerFatalError, bundlerRecompiling, browserRunnerDisabled, Playwrigh
|
|
|
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,
|
|
22
|
+
import { getURLDependencyMissing, findDroppedVendorKeys, isStaticThemeSource, entrySplitAcrossInitialFiles, isStaticTheme, fetchedFileDependencyMissing, filterKeysForThisBrowser, compiledSourceSpelling, importScriptsDependencyMissing, injectedFileDependencyMissing, injectedCompiledSourceLiteral, staticImportDependencyMissing, 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,330 @@ 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 edgeStoreKeyDropped(browser) {
|
|
1197
|
+
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.`;
|
|
1198
|
+
}
|
|
1199
|
+
function mv2SandboxPolicyDropped(browser) {
|
|
1200
|
+
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.`;
|
|
1201
|
+
}
|
|
1202
|
+
function geckoSidePanelUnsupported(file) {
|
|
1203
|
+
const lines = [];
|
|
1204
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.sidePanel, which is Chromium only.`);
|
|
1205
|
+
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.`);
|
|
1206
|
+
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.`);
|
|
1207
|
+
return lines.join('\n');
|
|
1208
|
+
}
|
|
1209
|
+
function safariUnsupportedApi(file, api, detail) {
|
|
1210
|
+
const lines = [];
|
|
1211
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} calls chrome.${api}, which Safari does not have.`);
|
|
1212
|
+
lines.push(detail);
|
|
1213
|
+
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}?.`)}.`);
|
|
1214
|
+
return lines.join('\n');
|
|
1215
|
+
}
|
|
1216
|
+
const safariBackgroundDies = "The call throws when the script runs, Safari drops the background, and nothing reports an error.";
|
|
1217
|
+
function safariSidePanelUnsupported(file) {
|
|
1218
|
+
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.");
|
|
1219
|
+
}
|
|
1220
|
+
function safariOffscreenUnsupported(file) {
|
|
1221
|
+
return safariUnsupportedApi(file, 'offscreen', `Safari has no offscreen documents, so that DOM work has no place to run. ${safariBackgroundDies}`);
|
|
1222
|
+
}
|
|
1223
|
+
function safariTabGroupsUnsupported(file) {
|
|
1224
|
+
return safariUnsupportedApi(file, 'tabGroups', `Safari has no tab groups, and its tabs carry no group id. ${safariBackgroundDies}`);
|
|
1225
|
+
}
|
|
1226
|
+
function safariManagementUnsupported(file) {
|
|
1227
|
+
return safariUnsupportedApi(file, 'management', `Safari exposes no management namespace at all, not even getSelf. ${safariBackgroundDies}`);
|
|
1228
|
+
}
|
|
1229
|
+
function safariUserScriptsUnsupported(file) {
|
|
1230
|
+
return safariUnsupportedApi(file, 'userScripts', `Safari has no userScripts namespace, and scripting.registerContentScripts is the closest it offers. ${safariBackgroundDies}`);
|
|
1231
|
+
}
|
|
1232
|
+
function safariIdentityUnsupported(file) {
|
|
1233
|
+
return safariUnsupportedApi(file, 'identity', `Safari has no identity namespace, and Apple points OAuth flows at a normal tab instead. ${safariBackgroundDies}`);
|
|
1234
|
+
}
|
|
1235
|
+
function safariNotificationsUnsupported(file) {
|
|
1236
|
+
return safariUnsupportedApi(file, 'notifications', `Safari has no notifications namespace, so a page has to raise the web Notification instead. ${safariBackgroundDies}`);
|
|
1237
|
+
}
|
|
1238
|
+
function safariOmniboxUnsupported(file) {
|
|
1239
|
+
return safariUnsupportedApi(file, 'omnibox', `Safari has no omnibox keyword API. ${safariBackgroundDies}`);
|
|
1240
|
+
}
|
|
1241
|
+
function safariBookmarksUnsupported(file) {
|
|
1242
|
+
return safariUnsupportedApi(file, 'bookmarks', `Safari does not expose bookmarks to extensions on any version. ${safariBackgroundDies}`);
|
|
1243
|
+
}
|
|
1244
|
+
function safariHistoryUnsupported(file) {
|
|
1245
|
+
return safariUnsupportedApi(file, 'history', `Safari does not expose browsing history to extensions on any version. ${safariBackgroundDies}`);
|
|
1246
|
+
}
|
|
1247
|
+
function safariDownloadsUnsupported(file) {
|
|
1248
|
+
return safariUnsupportedApi(file, 'downloads', `Safari has no downloads namespace. ${safariBackgroundDies}`);
|
|
1249
|
+
}
|
|
1250
|
+
function safariIdleUnsupported(file) {
|
|
1251
|
+
return safariUnsupportedApi(file, 'idle', `Safari has no idle namespace. ${safariBackgroundDies}`);
|
|
1252
|
+
}
|
|
1253
|
+
const safariMissingMemberDetails = {
|
|
1254
|
+
'action.getUserSettings': `Safari has no pinned-state query for the toolbar button, so there is no function to call. ${safariBackgroundDies}`,
|
|
1255
|
+
'action.getBadgeTextColor': `Safari draws the badge in its own colors and offers no badge text color call. ${safariBackgroundDies}`,
|
|
1256
|
+
'action.setBadgeTextColor': `Safari draws the badge in its own colors and offers no badge text color call. ${safariBackgroundDies}`,
|
|
1257
|
+
'action.onUserSettingsChanged': `Safari raises no event when the toolbar button settings change, so the listener attaches to nothing. ${safariBackgroundDies}`,
|
|
1258
|
+
'storage.managed': `Safari has no managed storage area, since it carries no enterprise policy channel for web extensions. ${safariBackgroundDies}`,
|
|
1259
|
+
'runtime.getContexts': `Safari keeps no inventory of extension contexts to hand back. ${safariBackgroundDies}`,
|
|
1260
|
+
'runtime.onSuspend': `Safari tears a background down without announcing it, so this lifecycle event does not exist. ${safariBackgroundDies}`,
|
|
1261
|
+
'runtime.onSuspendCanceled': `Safari tears a background down without announcing it, so this lifecycle event does not exist. ${safariBackgroundDies}`,
|
|
1262
|
+
'runtime.onUpdateAvailable': `Safari ships an extension inside its host app, so the browser raises no update event for it. ${safariBackgroundDies}`,
|
|
1263
|
+
'declarativeNetRequest.getAvailableStaticRuleCount': `Safari implements the blocking core of declarativeNetRequest and not its rule-budget queries. ${safariBackgroundDies}`,
|
|
1264
|
+
'declarativeNetRequest.getDisabledRuleIds': `Safari cannot disable individual static rules, so it has nothing to report here. ${safariBackgroundDies}`,
|
|
1265
|
+
'declarativeNetRequest.updateStaticRules': `Safari cannot toggle individual static rules, only whole rulesets through updateEnabledRulesets. ${safariBackgroundDies}`,
|
|
1266
|
+
'declarativeNetRequest.testMatchOutcome': `Safari has no rule-matching test harness, which is a Chrome debugging aid. ${safariBackgroundDies}`,
|
|
1267
|
+
'declarativeNetRequest.onRuleMatchedDebug': `Safari raises no rule-match debug event, which Chrome offers to unpacked extensions only. ${safariBackgroundDies}`,
|
|
1268
|
+
'tabs.group': `Safari has no tab groups at all, so there is no group to move a tab into. ${safariBackgroundDies}`,
|
|
1269
|
+
'tabs.ungroup': `Safari has no tab groups at all, so there is no group to take a tab out of. ${safariBackgroundDies}`,
|
|
1270
|
+
'webNavigation.onCreatedNavigationTarget': `Safari reports the main navigation events only, and this one is not among them. ${safariBackgroundDies}`,
|
|
1271
|
+
'webNavigation.onHistoryStateUpdated': `Safari reports the main navigation events only, so a History API navigation goes unannounced. ${safariBackgroundDies}`,
|
|
1272
|
+
'webNavigation.onReferenceFragmentUpdated': `Safari reports the main navigation events only, so a fragment change goes unannounced. ${safariBackgroundDies}`,
|
|
1273
|
+
'webNavigation.onTabReplaced': `Safari reports the main navigation events only, and this one is not among them. ${safariBackgroundDies}`,
|
|
1274
|
+
'windows.onBoundsChanged': `Safari raises no event when a window is moved or resized. ${safariBackgroundDies}`
|
|
1275
|
+
};
|
|
1276
|
+
function safariMemberUnsupported(file, api, member, kind) {
|
|
1277
|
+
const guard = 'call' === kind ? `chrome.${api}.${member}?.()` : `chrome.${api}.${member}?.`;
|
|
1278
|
+
const lines = [];
|
|
1279
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} calls chrome.${api}.${member}, which Safari does not have.`);
|
|
1280
|
+
lines.push(safariMissingMemberDetails[`${api}.${member}`] || `Safari ships chrome.${api} without this member. ${safariBackgroundDies}`);
|
|
1281
|
+
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)}.`);
|
|
1282
|
+
return lines.join('\n');
|
|
1283
|
+
}
|
|
1284
|
+
function geckoActionUnsupportedOnMv2(file) {
|
|
1285
|
+
const lines = [];
|
|
1286
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.action, which Manifest V2 does not have on Firefox.`);
|
|
1287
|
+
lines.push("Firefox Manifest V2 exposes the toolbar button as browserAction, and addons-linter flags the call as UNSUPPORTED_API.");
|
|
1288
|
+
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')}.`);
|
|
1289
|
+
return lines.join('\n');
|
|
1290
|
+
}
|
|
1291
|
+
function webkitUnsupportedKeysDropped(browser, dropped) {
|
|
1292
|
+
const count = dropped.length;
|
|
1293
|
+
const lines = [];
|
|
1294
|
+
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'}.`);
|
|
1295
|
+
for (const entry of dropped)lines.push(`${pintor.yellow(entry.path)} ${pintor.gray(entry.reason)}`);
|
|
1296
|
+
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.`);
|
|
1297
|
+
return lines.join('\n');
|
|
1298
|
+
}
|
|
1299
|
+
const UNSUPPORTED_TOP_LEVEL_KEYS = {
|
|
1300
|
+
side_panel: 'Safari has no side panel surface',
|
|
1301
|
+
sandbox: 'Safari cannot run sandboxed extension pages',
|
|
1302
|
+
user_scripts: 'Safari has no userScripts API',
|
|
1303
|
+
omnibox: 'Safari has no omnibox keyword API',
|
|
1304
|
+
chrome_settings_overrides: 'Safari lets no extension override these settings',
|
|
1305
|
+
tts_engine: 'Safari has no speech engine API',
|
|
1306
|
+
file_browser_handlers: 'ChromeOS only',
|
|
1307
|
+
input_components: 'ChromeOS only',
|
|
1308
|
+
cross_origin_embedder_policy: 'Safari reads no COEP key from a manifest',
|
|
1309
|
+
cross_origin_opener_policy: 'Safari reads no COOP key from a manifest',
|
|
1310
|
+
requirements: 'Chrome Web Store only',
|
|
1311
|
+
oauth2: 'Safari has no identity API to consume it',
|
|
1312
|
+
nacl_modules: 'Native Client is Chrome only',
|
|
1313
|
+
replacement_web_app: 'Chrome Web Store only',
|
|
1314
|
+
offline_enabled: 'Chrome Web Store only',
|
|
1315
|
+
differential_fingerprint: 'Chrome Web Store only',
|
|
1316
|
+
incognito: 'Safari always runs extensions in spanning mode and ignores the declared value'
|
|
1317
|
+
};
|
|
1318
|
+
const UNSUPPORTED_PERMISSIONS = new Set([
|
|
1319
|
+
'accessibilityFeatures.modify',
|
|
1320
|
+
'accessibilityFeatures.read',
|
|
1321
|
+
'audio',
|
|
1322
|
+
'background',
|
|
1323
|
+
'bookmarks',
|
|
1324
|
+
'browsingData',
|
|
1325
|
+
'certificateProvider',
|
|
1326
|
+
'clipboardRead',
|
|
1327
|
+
'contentSettings',
|
|
1328
|
+
'debugger',
|
|
1329
|
+
'declarativeContent',
|
|
1330
|
+
'desktopCapture',
|
|
1331
|
+
'documentScan',
|
|
1332
|
+
'downloads',
|
|
1333
|
+
'enterprise.deviceAttributes',
|
|
1334
|
+
'enterprise.platformKeys',
|
|
1335
|
+
'experimental',
|
|
1336
|
+
'favicon',
|
|
1337
|
+
'fileSystemProvider',
|
|
1338
|
+
'fontSettings',
|
|
1339
|
+
'gcm',
|
|
1340
|
+
'geolocation',
|
|
1341
|
+
'history',
|
|
1342
|
+
'identity',
|
|
1343
|
+
'identity.email',
|
|
1344
|
+
'idle',
|
|
1345
|
+
'management',
|
|
1346
|
+
'notifications',
|
|
1347
|
+
'offscreen',
|
|
1348
|
+
'pageCapture',
|
|
1349
|
+
'platformKeys',
|
|
1350
|
+
'power',
|
|
1351
|
+
'printerProvider',
|
|
1352
|
+
'privacy',
|
|
1353
|
+
'processes',
|
|
1354
|
+
'proxy',
|
|
1355
|
+
'readingList',
|
|
1356
|
+
'search',
|
|
1357
|
+
'sessions',
|
|
1358
|
+
'sidePanel',
|
|
1359
|
+
'system.cpu',
|
|
1360
|
+
'system.display',
|
|
1361
|
+
'system.memory',
|
|
1362
|
+
'system.storage',
|
|
1363
|
+
'systemLog',
|
|
1364
|
+
'tabCapture',
|
|
1365
|
+
'tabGroups',
|
|
1366
|
+
'topSites',
|
|
1367
|
+
'tts',
|
|
1368
|
+
'ttsEngine',
|
|
1369
|
+
'userScripts',
|
|
1370
|
+
'vpnProvider',
|
|
1371
|
+
'wallpaper',
|
|
1372
|
+
'webAuthenticationProxy',
|
|
1373
|
+
'webRequestBlocking'
|
|
1374
|
+
]);
|
|
1375
|
+
const PERMISSION_LISTS = [
|
|
1376
|
+
'permissions',
|
|
1377
|
+
'optional_permissions'
|
|
1378
|
+
];
|
|
1379
|
+
const UNSUPPORTED_OPTIONS_UI_KEYS = {
|
|
1380
|
+
open_in_tab: 'Safari always opens the options page in a tab'
|
|
1381
|
+
};
|
|
1382
|
+
function isPlainObject(value) {
|
|
1383
|
+
return !!value && 'object' == typeof value && !Array.isArray(value);
|
|
1384
|
+
}
|
|
1385
|
+
function dropWebkitUnsupportedKeys(manifest, browser) {
|
|
1386
|
+
const dropped = [];
|
|
1387
|
+
if (!isWebkitBasedBrowser(String(browser))) return {
|
|
1388
|
+
manifest,
|
|
1389
|
+
dropped
|
|
1390
|
+
};
|
|
1391
|
+
const next = {
|
|
1392
|
+
...manifest
|
|
1393
|
+
};
|
|
1394
|
+
for (const [key, reason] of Object.entries(UNSUPPORTED_TOP_LEVEL_KEYS))if (key in next) {
|
|
1395
|
+
delete next[key];
|
|
1396
|
+
dropped.push({
|
|
1397
|
+
path: key,
|
|
1398
|
+
reason
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
for (const listName of PERMISSION_LISTS){
|
|
1402
|
+
const list = next[listName];
|
|
1403
|
+
if (!Array.isArray(list)) continue;
|
|
1404
|
+
const kept = list.filter((entry)=>{
|
|
1405
|
+
if ('string' != typeof entry || !UNSUPPORTED_PERMISSIONS.has(entry)) return true;
|
|
1406
|
+
dropped.push({
|
|
1407
|
+
path: `${listName}.${entry}`,
|
|
1408
|
+
reason: `Safari has no ${entry} API`
|
|
1409
|
+
});
|
|
1410
|
+
return false;
|
|
1411
|
+
});
|
|
1412
|
+
if (kept.length !== list.length) if (0 === kept.length) delete next[listName];
|
|
1413
|
+
else next[listName] = kept;
|
|
1414
|
+
}
|
|
1415
|
+
const optionsUi = next.options_ui;
|
|
1416
|
+
if (isPlainObject(optionsUi)) {
|
|
1417
|
+
const patched = {
|
|
1418
|
+
...optionsUi
|
|
1419
|
+
};
|
|
1420
|
+
let changed = false;
|
|
1421
|
+
for (const [key, reason] of Object.entries(UNSUPPORTED_OPTIONS_UI_KEYS))if (key in patched) {
|
|
1422
|
+
delete patched[key];
|
|
1423
|
+
changed = true;
|
|
1424
|
+
dropped.push({
|
|
1425
|
+
path: `options_ui.${key}`,
|
|
1426
|
+
reason
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
if (changed) next.options_ui = patched;
|
|
1430
|
+
}
|
|
1431
|
+
return {
|
|
1432
|
+
manifest: next,
|
|
1433
|
+
dropped
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
const reportedDrops = new Set();
|
|
1437
|
+
function reportWebkitDroppedKeys(dropped, browser) {
|
|
1438
|
+
if (0 === dropped.length) return;
|
|
1439
|
+
const signature = `${String(browser)}\0${dropped.map((entry)=>entry.path).join(',')}`;
|
|
1440
|
+
if (reportedDrops.has(signature)) return;
|
|
1441
|
+
reportedDrops.add(signature);
|
|
1442
|
+
humanLine(webkitUnsupportedKeysDropped(String(browser), dropped));
|
|
1443
|
+
}
|
|
1122
1444
|
const manifest_cjsRequire = createRequire(import.meta.url);
|
|
1123
1445
|
const manifestSourceStore = new WeakMap();
|
|
1124
1446
|
function manifestSourceEntry(compilation) {
|
|
@@ -1185,11 +1507,15 @@ function getManifestContent(compilation, manifestPath) {
|
|
|
1185
1507
|
function buildCanonicalManifest(manifestPath, manifest, browser, projectPath) {
|
|
1186
1508
|
const filteredManifest = filterKeysForThisBrowser(manifest, browser);
|
|
1187
1509
|
const forOverrides = shouldDropPageAction(filteredManifest, browser) ? dropPageAction(filteredManifest) : filteredManifest;
|
|
1188
|
-
|
|
1510
|
+
const canonical = dropMv2ObjectPolicy(dropMv2HostKeys({
|
|
1189
1511
|
...forOverrides,
|
|
1190
1512
|
...JSON.parse(getManifestOverrides(manifestPath, forOverrides, projectPath))
|
|
1191
1513
|
}));
|
|
1514
|
+
const webkit = dropWebkitUnsupportedKeys(canonical, browser);
|
|
1515
|
+
reportWebkitDroppedKeys(webkit.dropped, browser);
|
|
1516
|
+
return webkit.manifest;
|
|
1192
1517
|
}
|
|
1518
|
+
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}})()';
|
|
1193
1519
|
function resolveProcessShim() {
|
|
1194
1520
|
const candidate = __rspack_external_node_path_806ed179.join(__rspack_import_meta_dirname__, '..', 'runtime', 'process-shim.cjs');
|
|
1195
1521
|
try {
|
|
@@ -1301,6 +1627,8 @@ class EnvPlugin {
|
|
|
1301
1627
|
filteredEnvVars['import.meta.env'] = JSON.stringify(importMetaEnvObject);
|
|
1302
1628
|
filteredEnvVars['import.meta.dirname'] = 'undefined';
|
|
1303
1629
|
filteredEnvVars['import.meta.filename'] = 'undefined';
|
|
1630
|
+
filteredEnvVars.global = 'globalThis';
|
|
1631
|
+
filteredEnvVars['import.meta.url'] = IMPORT_META_URL_RUNTIME;
|
|
1304
1632
|
const injectedCount = Object.keys(filteredEnvVars).filter((k)=>k.startsWith('process.env.EXTENSION_PUBLIC_')).length;
|
|
1305
1633
|
if (isDebug()) console.log(envInjectedPublicVars(injectedCount));
|
|
1306
1634
|
const processShim = resolveProcessShim();
|
|
@@ -2760,6 +3088,21 @@ function isUsingVue(projectPath) {
|
|
|
2760
3088
|
}
|
|
2761
3089
|
return using;
|
|
2762
3090
|
}
|
|
3091
|
+
function resolveVueBundlerEntry(requireFromProject, id) {
|
|
3092
|
+
try {
|
|
3093
|
+
const manifestPath = requireFromProject.resolve(`${id}/package.json`);
|
|
3094
|
+
const manifest = JSON.parse(__rspack_external_node_fs_1b05aee1.readFileSync(manifestPath, 'utf8'));
|
|
3095
|
+
if ('string' == typeof manifest.module && manifest.module) {
|
|
3096
|
+
const entry = __rspack_external_node_path_806ed179.join(__rspack_external_node_path_806ed179.dirname(manifestPath), manifest.module);
|
|
3097
|
+
if (__rspack_external_node_fs_1b05aee1.existsSync(entry)) return entry;
|
|
3098
|
+
}
|
|
3099
|
+
} catch {}
|
|
3100
|
+
try {
|
|
3101
|
+
return requireFromProject.resolve(id);
|
|
3102
|
+
} catch {
|
|
3103
|
+
return;
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
2763
3106
|
async function maybeUseVue(projectPath, mode = 'development') {
|
|
2764
3107
|
if (!isUsingVue(projectPath)) return;
|
|
2765
3108
|
const vueLoaderPath = await ensureOptionalContractPackageResolved({
|
|
@@ -2790,19 +3133,13 @@ async function maybeUseVue(projectPath, mode = 'development') {
|
|
|
2790
3133
|
const defaultPlugins = [
|
|
2791
3134
|
new VueLoaderPlugin(),
|
|
2792
3135
|
new DefinePlugin({
|
|
2793
|
-
__VUE_OPTIONS_API__: JSON.stringify(
|
|
3136
|
+
__VUE_OPTIONS_API__: JSON.stringify(true),
|
|
2794
3137
|
__VUE_PROD_DEVTOOLS__: JSON.stringify(!isProd),
|
|
2795
3138
|
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(!isProd)
|
|
2796
3139
|
})
|
|
2797
3140
|
];
|
|
2798
3141
|
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
2799
|
-
const resolveFromProject = (id)=>
|
|
2800
|
-
try {
|
|
2801
|
-
return requireFromProject.resolve(id);
|
|
2802
|
-
} catch {
|
|
2803
|
-
return;
|
|
2804
|
-
}
|
|
2805
|
-
};
|
|
3142
|
+
const resolveFromProject = (id)=>resolveVueBundlerEntry(requireFromProject, id);
|
|
2806
3143
|
const alias = {};
|
|
2807
3144
|
const vuePath = resolveFromProject('vue');
|
|
2808
3145
|
const vueRuntimeDom = resolveFromProject('@vue/runtime-dom');
|
|
@@ -3519,14 +3856,28 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3519
3856
|
var connectFailures = 0;
|
|
3520
3857
|
var MAX_QUEUE = 1000;
|
|
3521
3858
|
var MAX_RESULT_BYTES = 256 * 1024;
|
|
3859
|
+
// Where error frames are parked so a context that dies before its socket
|
|
3860
|
+
// opens does not take them along. Capped, and old entries are dropped.
|
|
3861
|
+
var PENDING_ERRORS_KEY = "__extjsPendingErrors";
|
|
3862
|
+
var MAX_PENDING_ERRORS = 20;
|
|
3863
|
+
var PENDING_ERROR_TTL = 300000;
|
|
3522
3864
|
|
|
3523
3865
|
function nowId() {
|
|
3524
3866
|
return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
3525
3867
|
}
|
|
3526
3868
|
|
|
3869
|
+
// The extension's own URL scheme names the engine outright, which beats a
|
|
3870
|
+
// user agent where Chrome and Safari both say "Safari".
|
|
3527
3871
|
function engineName() {
|
|
3528
3872
|
try {
|
|
3529
|
-
|
|
3873
|
+
var scheme = (typeof location !== "undefined" && location.protocol) || "";
|
|
3874
|
+
if (scheme.indexOf("safari-web-extension") === 0) return "webkit";
|
|
3875
|
+
if (scheme.indexOf("moz-extension") === 0) return "firefox";
|
|
3876
|
+
if (scheme.indexOf("chrome-extension") === 0) return "chromium";
|
|
3877
|
+
var ua = (typeof navigator !== "undefined" && navigator.userAgent) || "";
|
|
3878
|
+
if (/firefox/i.test(ua)) return "firefox";
|
|
3879
|
+
if (/safari/i.test(ua) && !/chrome|chromium|edg/i.test(ua)) return "webkit";
|
|
3880
|
+
return "chromium";
|
|
3530
3881
|
} catch (e) { return "chromium"; }
|
|
3531
3882
|
}
|
|
3532
3883
|
|
|
@@ -3675,7 +4026,7 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3675
4026
|
// MV3 forbids eval of strings in the SW/extension pages and
|
|
3676
4027
|
// rejects 'unsafe-eval'. Surface it honestly with an alternative.
|
|
3677
4028
|
if (/Content Security Policy|unsafe-eval/i.test(msg)) {
|
|
3678
|
-
replyErr(cmdId, "Unsupported", "eval is blocked in the
|
|
4029
|
+
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());
|
|
3679
4030
|
} else {
|
|
3680
4031
|
replyErr(cmdId, (e && e.name) || "EvalError", msg);
|
|
3681
4032
|
}
|
|
@@ -3825,6 +4176,11 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
3825
4176
|
try { chrome.runtime.openOptionsPage(function () { replyOk(cmdId, {opened: "options"}); }); }
|
|
3826
4177
|
catch (e) { replyErr(cmdId, "Unsupported", "openOptionsPage: " + e); }
|
|
3827
4178
|
} else if (surface === "sidebar") {
|
|
4179
|
+
// The two member reads below are exactly what the Safari
|
|
4180
|
+
// unsupported-API scan looks for, and this runtime is prepended to
|
|
4181
|
+
// the background asset at PROCESS_ASSETS_STAGE_REPORT + 101, after
|
|
4182
|
+
// that scan runs at SUMMARIZE + 1. Move the injection earlier and
|
|
4183
|
+
// every Safari dev session warns about this line.
|
|
3828
4184
|
if (chrome.sidePanel && chrome.sidePanel.open && chrome.windows) {
|
|
3829
4185
|
chrome.windows.getCurrent(function (w) {
|
|
3830
4186
|
nsCall("sidePanel", "open", [{windowId: w.id}], function (err) {
|
|
@@ -4277,6 +4633,80 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
4277
4633
|
}
|
|
4278
4634
|
}
|
|
4279
4635
|
if (queue.length < MAX_QUEUE) queue.push(frame);
|
|
4636
|
+
parkPendingError(frame);
|
|
4637
|
+
}
|
|
4638
|
+
|
|
4639
|
+
// The queue above lives in this context's memory only, so a background
|
|
4640
|
+
// that throws while it evaluates dies with the error still queued: the
|
|
4641
|
+
// socket has not finished its handshake yet. Park error frames in
|
|
4642
|
+
// extension storage too, where the NEXT context to connect can ship them.
|
|
4643
|
+
// Best effort by construction: the write is asynchronous, so a teardown
|
|
4644
|
+
// can cut it before the browser records anything.
|
|
4645
|
+
var parkedErrors = [];
|
|
4646
|
+
function storageLocalArea() {
|
|
4647
|
+
try {
|
|
4648
|
+
var ns = (g.chrome && g.chrome.storage) || (g.browser && g.browser.storage);
|
|
4649
|
+
var area = ns && ns.local;
|
|
4650
|
+
if (!area || typeof area.get !== "function" || typeof area.set !== "function") return null;
|
|
4651
|
+
return area;
|
|
4652
|
+
} catch (e) { return null; }
|
|
4653
|
+
}
|
|
4654
|
+
function parkPendingError(frame) {
|
|
4655
|
+
if (open) return;
|
|
4656
|
+
if (!frame || frame.type !== "log" || !frame.event || frame.event.level !== "error") return;
|
|
4657
|
+
var area = storageLocalArea();
|
|
4658
|
+
if (!area) return;
|
|
4659
|
+
// The whole list is rewritten on every park, so two errors in one turn
|
|
4660
|
+
// cannot lose each other to a read-modify-write, and the cap holds.
|
|
4661
|
+
parkedErrors.push(frame);
|
|
4662
|
+
while (parkedErrors.length > MAX_PENDING_ERRORS) parkedErrors.shift();
|
|
4663
|
+
var items = {};
|
|
4664
|
+
items[PENDING_ERRORS_KEY] = parkedErrors;
|
|
4665
|
+
try { area.set(items, noopLastError); } catch (e) {
|
|
4666
|
+
// Ignore
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
function parkedHere(id) {
|
|
4670
|
+
for (var i = 0; i < parkedErrors.length; i++) {
|
|
4671
|
+
var ev = parkedErrors[i] && parkedErrors[i].event;
|
|
4672
|
+
if (ev && ev.id === id) return true;
|
|
4673
|
+
}
|
|
4674
|
+
return false;
|
|
4675
|
+
}
|
|
4676
|
+
// Ship what an earlier context parked and never got to send. Entries from
|
|
4677
|
+
// another build (a different instance id) or from an older run are dropped,
|
|
4678
|
+
// and the key is cleared on read so one failure is reported once.
|
|
4679
|
+
function flushPendingErrors() {
|
|
4680
|
+
var area = storageLocalArea();
|
|
4681
|
+
if (!area) return;
|
|
4682
|
+
var read = false;
|
|
4683
|
+
function onRead(res) {
|
|
4684
|
+
if (read) return;
|
|
4685
|
+
read = true;
|
|
4686
|
+
var list = res && res[PENDING_ERRORS_KEY];
|
|
4687
|
+
if (!list || !list.length) return;
|
|
4688
|
+
try {
|
|
4689
|
+
if (typeof area.remove === "function") area.remove(PENDING_ERRORS_KEY, noopLastError);
|
|
4690
|
+
} catch (e) {
|
|
4691
|
+
// Ignore
|
|
4692
|
+
}
|
|
4693
|
+
var now = Date.now();
|
|
4694
|
+
for (var i = 0; i < list.length; i++) {
|
|
4695
|
+
var frame = list[i];
|
|
4696
|
+
var ev = frame && frame.event;
|
|
4697
|
+
if (!ev || ev.runId !== INSTANCE_ID) continue;
|
|
4698
|
+
// This context parked it, so the queue flush above already has it.
|
|
4699
|
+
if (parkedHere(ev.id)) continue;
|
|
4700
|
+
if (typeof ev.timestamp !== "number" || now - ev.timestamp > PENDING_ERROR_TTL) continue;
|
|
4701
|
+
send(frame);
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
try {
|
|
4705
|
+
var ret = area.get(PENDING_ERRORS_KEY, function (res) { noopLastError(); onRead(res); });
|
|
4706
|
+
if (ret && typeof ret.then === "function") ret.then(onRead, function () {});
|
|
4707
|
+
} catch (e) {
|
|
4708
|
+
// Ignore
|
|
4709
|
+
}
|
|
4280
4710
|
}
|
|
4281
4711
|
|
|
4282
4712
|
// The baked PORT is a snapshot of an ephemeral port. After a dev-server
|
|
@@ -4330,6 +4760,9 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
4330
4760
|
// Ignore
|
|
4331
4761
|
}
|
|
4332
4762
|
flush();
|
|
4763
|
+
// Hello went first and this context's own queue is out; now replay any
|
|
4764
|
+
// error a previous context parked before it died.
|
|
4765
|
+
flushPendingErrors();
|
|
4333
4766
|
};
|
|
4334
4767
|
socket.onmessage = function (ev) {
|
|
4335
4768
|
var frame;
|
|
@@ -4797,10 +5230,12 @@ class InjectBridgeProducer {
|
|
|
4797
5230
|
name: InjectBridgeProducer.name,
|
|
4798
5231
|
stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 101
|
|
4799
5232
|
}, ()=>{
|
|
4800
|
-
|
|
5233
|
+
const controlAsset = new core_sources.RawSource(JSON.stringify({
|
|
4801
5234
|
port: controlPort,
|
|
4802
5235
|
instanceId
|
|
4803
|
-
}))
|
|
5236
|
+
}));
|
|
5237
|
+
if (compilation.getAsset(CONTROL_PORT_ASSET_NAME)) compilation.updateAsset(CONTROL_PORT_ASSET_NAME, controlAsset);
|
|
5238
|
+
else compilation.emitAsset(CONTROL_PORT_ASSET_NAME, controlAsset);
|
|
4804
5239
|
for (const asset of compilation.getAssets()){
|
|
4805
5240
|
if (!BACKGROUND_ASSET.test(asset.name)) continue;
|
|
4806
5241
|
const original = asset.source.source().toString();
|
|
@@ -9525,17 +9960,17 @@ function isManagedSchemaFeature(feature) {
|
|
|
9525
9960
|
function isCriticalJsonFeature(feature) {
|
|
9526
9961
|
return feature.startsWith('declarative_net_request') || isManagedSchemaFeature(feature);
|
|
9527
9962
|
}
|
|
9528
|
-
function
|
|
9963
|
+
function json_validation_isPlainObject(value) {
|
|
9529
9964
|
return 'object' == typeof value && null !== value && !Array.isArray(value);
|
|
9530
9965
|
}
|
|
9531
9966
|
function getDnrRuleRejection(rule) {
|
|
9532
|
-
if (!
|
|
9967
|
+
if (!json_validation_isPlainObject(rule)) return 'the rule is not an object';
|
|
9533
9968
|
const id = rule.id;
|
|
9534
9969
|
if ('number' != typeof id || !Number.isInteger(id) || id < 1) return 'the rule id is not a positive integer';
|
|
9535
9970
|
const action = rule.action;
|
|
9536
|
-
if (!
|
|
9971
|
+
if (!json_validation_isPlainObject(action)) return 'the rule has no action object';
|
|
9537
9972
|
if ('string' != typeof action.type || 0 === action.type.length) return 'the rule action has no type';
|
|
9538
|
-
if (!
|
|
9973
|
+
if (!json_validation_isPlainObject(rule.condition)) return 'the rule has no condition object';
|
|
9539
9974
|
}
|
|
9540
9975
|
function getDnrRuleSoftIssue(rule) {
|
|
9541
9976
|
const priority = rule.priority;
|
|
@@ -10048,95 +10483,6 @@ class LocalesPlugin {
|
|
|
10048
10483
|
});
|
|
10049
10484
|
}
|
|
10050
10485
|
}
|
|
10051
|
-
function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
|
|
10052
|
-
const lines = [];
|
|
10053
|
-
lines.push("Entrypoint references changed.");
|
|
10054
|
-
if (fileRemoved) lines.push(`${pintor.gray('EXPECTED')} ${pintor.underline(fileRemoved)}`);
|
|
10055
|
-
if (fileAdded) lines.push(`${pintor.gray('GOT')} ${pintor.underline(fileAdded)}`);
|
|
10056
|
-
lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
|
|
10057
|
-
return lines.join('\n');
|
|
10058
|
-
}
|
|
10059
|
-
function legacyManifestPathWarning(field, legacyPath, modernPath) {
|
|
10060
|
-
const lines = [];
|
|
10061
|
-
lines.push(`${messaging_prefix('warn')} The ${pintor.blue(field)} field uses a deprecated scaffold path.`);
|
|
10062
|
-
lines.push(`${pintor.gray('PATH')} ${pintor.underline(legacyPath)}`);
|
|
10063
|
-
lines.push(`Point it at ${pintor.underline(modernPath)}, Extension.js already emits the page there.`);
|
|
10064
|
-
return lines.join('\n');
|
|
10065
|
-
}
|
|
10066
|
-
function fatalManifestShapeFixed(field, detail) {
|
|
10067
|
-
const lines = [];
|
|
10068
|
-
lines.push(`${messaging_prefix('warn')} Repaired the ${pintor.blue(field)} field, which Chrome refuses to load the extension over.`);
|
|
10069
|
-
lines.push(`${pintor.gray('REASON')} ${pintor.underline(detail)}`);
|
|
10070
|
-
lines.push(`Fix the field in your ${pintor.blue('manifest.json')} file.`);
|
|
10071
|
-
return lines.join('\n');
|
|
10072
|
-
}
|
|
10073
|
-
function invalidThemeValue(field, detail, value) {
|
|
10074
|
-
const lines = [];
|
|
10075
|
-
lines.push(`Check the ${pintor.yellow(field)} field in your ${pintor.yellow('manifest.json')} file.`);
|
|
10076
|
-
lines.push(detail);
|
|
10077
|
-
lines.push(`Chrome rejects the whole extension when this value is malformed.\nThe build stops here to protect you.`);
|
|
10078
|
-
lines.push('');
|
|
10079
|
-
lines.push(`${pintor.red('INVALID VALUE')} ${value}`);
|
|
10080
|
-
return lines.join('\n');
|
|
10081
|
-
}
|
|
10082
|
-
function themeNotSupportedByBrowser(browser) {
|
|
10083
|
-
const lines = [];
|
|
10084
|
-
lines.push(`${messaging_prefix('warn')} ${pintor.blue(browser)} does not support the ${pintor.yellow('theme')} field.`);
|
|
10085
|
-
lines.push("The field ships unchanged in the manifest and Safari ignores it.");
|
|
10086
|
-
return lines.join('\n');
|
|
10087
|
-
}
|
|
10088
|
-
function missingGeckoDataCollectionPermissions() {
|
|
10089
|
-
const lines = [];
|
|
10090
|
-
lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.blue('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
|
|
10091
|
-
lines.push(`Declare ${pintor.blue('{"required": ["none"]}')} if this extension transmits no data.`);
|
|
10092
|
-
lines.push(`See ${pintor.underline('https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/')} for details.`);
|
|
10093
|
-
return lines.join('\n');
|
|
10094
|
-
}
|
|
10095
|
-
function manifestInvalidError(error) {
|
|
10096
|
-
const lines = [];
|
|
10097
|
-
lines.push(`Can't read your ${pintor.blue('manifest.json')} file.`);
|
|
10098
|
-
lines.push(`${pintor.gray('REASON')} ${pintor.underline(String(error))}`);
|
|
10099
|
-
lines.push("Update your manifest and try again.");
|
|
10100
|
-
return lines.join('\n');
|
|
10101
|
-
}
|
|
10102
|
-
function manifestIncludeSummary(browser, manifestPath) {
|
|
10103
|
-
return `${messaging_prefix('debug')} manifest include browser=${browser} path=${manifestPath}`;
|
|
10104
|
-
}
|
|
10105
|
-
function manifestEmitSuccess() {
|
|
10106
|
-
return `${messaging_prefix('debug')} manifest emitted=true schemaStripped=true`;
|
|
10107
|
-
}
|
|
10108
|
-
function manifestOverridesSummary(overrideKeys, devCssStubsAdded) {
|
|
10109
|
-
return `${messaging_prefix('debug')} manifest overrides keys=${String(overrideKeys)} devCssStubs=${String(devCssStubsAdded)}`;
|
|
10110
|
-
}
|
|
10111
|
-
function manifestDepsTracked(addedCount) {
|
|
10112
|
-
return `${messaging_prefix('debug')} manifest deps=${String(addedCount)}`;
|
|
10113
|
-
}
|
|
10114
|
-
function manifestLegacyWarningsSummary(count) {
|
|
10115
|
-
return `${messaging_prefix('debug')} manifest legacyWarnings=${String(count)}`;
|
|
10116
|
-
}
|
|
10117
|
-
function pageActionNotSupportedByBrowser(browser) {
|
|
10118
|
-
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.`;
|
|
10119
|
-
}
|
|
10120
|
-
function pageActionDroppedForBrowserAction(browser) {
|
|
10121
|
-
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.`;
|
|
10122
|
-
}
|
|
10123
|
-
function mv2SandboxPolicyDropped(browser) {
|
|
10124
|
-
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.`;
|
|
10125
|
-
}
|
|
10126
|
-
function geckoSidePanelUnsupported(file) {
|
|
10127
|
-
const lines = [];
|
|
10128
|
-
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.sidePanel, which is Chromium only.`);
|
|
10129
|
-
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.`);
|
|
10130
|
-
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.`);
|
|
10131
|
-
return lines.join('\n');
|
|
10132
|
-
}
|
|
10133
|
-
function geckoActionUnsupportedOnMv2(file) {
|
|
10134
|
-
const lines = [];
|
|
10135
|
-
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.action, which Manifest V2 does not have on Firefox.`);
|
|
10136
|
-
lines.push("Firefox Manifest V2 exposes the toolbar button as browserAction, and addons-linter flags the call as UNSUPPORTED_API.");
|
|
10137
|
-
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')}.`);
|
|
10138
|
-
return lines.join('\n');
|
|
10139
|
-
}
|
|
10140
10486
|
class AddDependencies {
|
|
10141
10487
|
dependencyList;
|
|
10142
10488
|
constructor(dependencyList){
|
|
@@ -10566,9 +10912,9 @@ function findInjectedOnlyPermissionUses(compilation, declared, injected) {
|
|
|
10566
10912
|
if (!resource) continue;
|
|
10567
10913
|
let source;
|
|
10568
10914
|
try {
|
|
10569
|
-
const stat =
|
|
10915
|
+
const stat = __rspack_external_node_fs_1b05aee1.statSync(resource);
|
|
10570
10916
|
if (stat.size > 1048576) continue;
|
|
10571
|
-
source =
|
|
10917
|
+
source = __rspack_external_node_fs_1b05aee1.readFileSync(resource, 'utf-8');
|
|
10572
10918
|
} catch {
|
|
10573
10919
|
continue;
|
|
10574
10920
|
}
|
|
@@ -10662,7 +11008,7 @@ class ApplyDevDefaults {
|
|
|
10662
11008
|
const declared = new Set(canonicalManifest.permissions || []);
|
|
10663
11009
|
const uses = findInjectedOnlyPermissionUses(compilation, declared, injectedPermissions);
|
|
10664
11010
|
for (const [api, file] of uses){
|
|
10665
|
-
const relative =
|
|
11011
|
+
const relative = __rspack_external_node_path_806ed179.relative(__rspack_external_node_path_806ed179.dirname(this.manifestPath), file);
|
|
10666
11012
|
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.`;
|
|
10667
11013
|
pushDevWarning('DevInjectedPermissionWarning', optionalPermissions.has(api) ? text + partiallyGatedNote(api) : text);
|
|
10668
11014
|
}
|
|
@@ -10671,7 +11017,7 @@ class ApplyDevDefaults {
|
|
|
10671
11017
|
const injectedOnlyHosts = findInjectedOnlyHostUses(compilation.modules, contentScriptMatches, declaredHostPatterns(canonicalManifest), optionalHostPatterns(canonicalManifest));
|
|
10672
11018
|
const hostKey = 3 === canonicalManifest.manifest_version ? 'host_permissions' : 'permissions';
|
|
10673
11019
|
for (const use of injectedOnlyHosts){
|
|
10674
|
-
const relative =
|
|
11020
|
+
const relative = __rspack_external_node_path_806ed179.relative(__rspack_external_node_path_806ed179.dirname(this.manifestPath), use.file);
|
|
10675
11021
|
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.`;
|
|
10676
11022
|
pushDevWarning('DevInjectedHostWarning', text);
|
|
10677
11023
|
}
|
|
@@ -11658,6 +12004,22 @@ class PersistManifestToDisk {
|
|
|
11658
12004
|
});
|
|
11659
12005
|
}
|
|
11660
12006
|
}
|
|
12007
|
+
function dropEdgeStoreKey(manifest, browser) {
|
|
12008
|
+
if ('edge' !== String(browser)) return {
|
|
12009
|
+
manifest,
|
|
12010
|
+
dropped: false
|
|
12011
|
+
};
|
|
12012
|
+
const source = manifest;
|
|
12013
|
+
if (!('key' in source)) return {
|
|
12014
|
+
manifest,
|
|
12015
|
+
dropped: false
|
|
12016
|
+
};
|
|
12017
|
+
const { key: _key, ...rest } = source;
|
|
12018
|
+
return {
|
|
12019
|
+
manifest: rest,
|
|
12020
|
+
dropped: true
|
|
12021
|
+
};
|
|
12022
|
+
}
|
|
11661
12023
|
function gecko_data_collection_missingGeckoDataCollectionPermissions(manifest) {
|
|
11662
12024
|
const bss = manifest.browser_specific_settings;
|
|
11663
12025
|
const declaration = bss?.gecko?.data_collection_permissions;
|
|
@@ -12768,7 +13130,149 @@ function patchGeckoBackground(manifest, browser) {
|
|
|
12768
13130
|
}
|
|
12769
13131
|
};
|
|
12770
13132
|
}
|
|
12771
|
-
function
|
|
13133
|
+
function patchWebkitBackground(manifest, browser) {
|
|
13134
|
+
if (!isWebkitBasedBrowser(String(browser))) return manifest;
|
|
13135
|
+
const background = manifest.background;
|
|
13136
|
+
if (!background || !background.service_worker || background.scripts) return manifest;
|
|
13137
|
+
const { service_worker, type, ...rest } = background;
|
|
13138
|
+
return {
|
|
13139
|
+
...manifest,
|
|
13140
|
+
background: {
|
|
13141
|
+
...rest,
|
|
13142
|
+
scripts: [
|
|
13143
|
+
service_worker
|
|
13144
|
+
]
|
|
13145
|
+
}
|
|
13146
|
+
};
|
|
13147
|
+
}
|
|
13148
|
+
const webkitUnsupportedApis = {
|
|
13149
|
+
sidePanel: safariSidePanelUnsupported,
|
|
13150
|
+
offscreen: safariOffscreenUnsupported,
|
|
13151
|
+
tabGroups: safariTabGroupsUnsupported,
|
|
13152
|
+
management: safariManagementUnsupported,
|
|
13153
|
+
userScripts: safariUserScriptsUnsupported,
|
|
13154
|
+
identity: safariIdentityUnsupported,
|
|
13155
|
+
notifications: safariNotificationsUnsupported,
|
|
13156
|
+
omnibox: safariOmniboxUnsupported,
|
|
13157
|
+
bookmarks: safariBookmarksUnsupported,
|
|
13158
|
+
history: safariHistoryUnsupported,
|
|
13159
|
+
downloads: safariDownloadsUnsupported,
|
|
13160
|
+
idle: safariIdleUnsupported
|
|
13161
|
+
};
|
|
13162
|
+
const webkitUnsupportedMembers = [
|
|
13163
|
+
{
|
|
13164
|
+
api: 'action',
|
|
13165
|
+
member: 'getUserSettings',
|
|
13166
|
+
kind: 'call'
|
|
13167
|
+
},
|
|
13168
|
+
{
|
|
13169
|
+
api: 'action',
|
|
13170
|
+
member: 'getBadgeTextColor',
|
|
13171
|
+
kind: 'call'
|
|
13172
|
+
},
|
|
13173
|
+
{
|
|
13174
|
+
api: 'action',
|
|
13175
|
+
member: 'setBadgeTextColor',
|
|
13176
|
+
kind: 'call'
|
|
13177
|
+
},
|
|
13178
|
+
{
|
|
13179
|
+
api: 'action',
|
|
13180
|
+
member: 'onUserSettingsChanged',
|
|
13181
|
+
kind: 'read'
|
|
13182
|
+
},
|
|
13183
|
+
{
|
|
13184
|
+
api: 'storage',
|
|
13185
|
+
member: 'managed',
|
|
13186
|
+
kind: 'read'
|
|
13187
|
+
},
|
|
13188
|
+
{
|
|
13189
|
+
api: 'runtime',
|
|
13190
|
+
member: 'getContexts',
|
|
13191
|
+
kind: 'call'
|
|
13192
|
+
},
|
|
13193
|
+
{
|
|
13194
|
+
api: 'runtime',
|
|
13195
|
+
member: 'onSuspend',
|
|
13196
|
+
kind: 'read'
|
|
13197
|
+
},
|
|
13198
|
+
{
|
|
13199
|
+
api: 'runtime',
|
|
13200
|
+
member: 'onSuspendCanceled',
|
|
13201
|
+
kind: 'read'
|
|
13202
|
+
},
|
|
13203
|
+
{
|
|
13204
|
+
api: 'runtime',
|
|
13205
|
+
member: 'onUpdateAvailable',
|
|
13206
|
+
kind: 'read'
|
|
13207
|
+
},
|
|
13208
|
+
{
|
|
13209
|
+
api: 'declarativeNetRequest',
|
|
13210
|
+
member: 'getAvailableStaticRuleCount',
|
|
13211
|
+
kind: 'call'
|
|
13212
|
+
},
|
|
13213
|
+
{
|
|
13214
|
+
api: 'declarativeNetRequest',
|
|
13215
|
+
member: 'getDisabledRuleIds',
|
|
13216
|
+
kind: 'call'
|
|
13217
|
+
},
|
|
13218
|
+
{
|
|
13219
|
+
api: 'declarativeNetRequest',
|
|
13220
|
+
member: 'updateStaticRules',
|
|
13221
|
+
kind: 'call'
|
|
13222
|
+
},
|
|
13223
|
+
{
|
|
13224
|
+
api: 'declarativeNetRequest',
|
|
13225
|
+
member: 'testMatchOutcome',
|
|
13226
|
+
kind: 'call'
|
|
13227
|
+
},
|
|
13228
|
+
{
|
|
13229
|
+
api: 'declarativeNetRequest',
|
|
13230
|
+
member: 'onRuleMatchedDebug',
|
|
13231
|
+
kind: 'read'
|
|
13232
|
+
},
|
|
13233
|
+
{
|
|
13234
|
+
api: 'tabs',
|
|
13235
|
+
member: 'group',
|
|
13236
|
+
kind: 'call'
|
|
13237
|
+
},
|
|
13238
|
+
{
|
|
13239
|
+
api: 'tabs',
|
|
13240
|
+
member: 'ungroup',
|
|
13241
|
+
kind: 'call'
|
|
13242
|
+
},
|
|
13243
|
+
{
|
|
13244
|
+
api: 'webNavigation',
|
|
13245
|
+
member: 'onCreatedNavigationTarget',
|
|
13246
|
+
kind: 'read'
|
|
13247
|
+
},
|
|
13248
|
+
{
|
|
13249
|
+
api: 'webNavigation',
|
|
13250
|
+
member: 'onHistoryStateUpdated',
|
|
13251
|
+
kind: 'read'
|
|
13252
|
+
},
|
|
13253
|
+
{
|
|
13254
|
+
api: 'webNavigation',
|
|
13255
|
+
member: 'onReferenceFragmentUpdated',
|
|
13256
|
+
kind: 'read'
|
|
13257
|
+
},
|
|
13258
|
+
{
|
|
13259
|
+
api: 'webNavigation',
|
|
13260
|
+
member: 'onTabReplaced',
|
|
13261
|
+
kind: 'read'
|
|
13262
|
+
},
|
|
13263
|
+
{
|
|
13264
|
+
api: 'windows',
|
|
13265
|
+
member: 'onBoundsChanged',
|
|
13266
|
+
kind: 'read'
|
|
13267
|
+
}
|
|
13268
|
+
];
|
|
13269
|
+
const webkitMemberEntries = webkitUnsupportedMembers.filter((entry)=>!(entry.api in webkitUnsupportedApis));
|
|
13270
|
+
const webkitMemberByKey = new Map(webkitUnsupportedMembers.map((entry)=>[
|
|
13271
|
+
`${entry.api}.${entry.member}`,
|
|
13272
|
+
entry
|
|
13273
|
+
]));
|
|
13274
|
+
function geckoUnsupportedApis(manifestVersion, engine = 'gecko') {
|
|
13275
|
+
if ('webkit' === engine) return Object.keys(webkitUnsupportedApis);
|
|
12772
13276
|
return 2 === manifestVersion ? [
|
|
12773
13277
|
'sidePanel',
|
|
12774
13278
|
'action'
|
|
@@ -12776,10 +13280,31 @@ function geckoUnsupportedApis(manifestVersion) {
|
|
|
12776
13280
|
'sidePanel'
|
|
12777
13281
|
];
|
|
12778
13282
|
}
|
|
12779
|
-
function usesGeckoUnsupportedApi(source, api) {
|
|
12780
|
-
const
|
|
13283
|
+
function usesGeckoUnsupportedApi(source, api, engine = 'gecko') {
|
|
13284
|
+
const chain = 'webkit' === engine ? '' : '\\??';
|
|
13285
|
+
const memberRe = new RegExp(`\\b(?:chrome|browser)\\s*\\.\\s*${api}\\s*${chain}\\.\\s*[A-Za-z_$]`);
|
|
13286
|
+
return memberRe.test(source);
|
|
13287
|
+
}
|
|
13288
|
+
function usesWebkitUnsupportedMember(source, entry) {
|
|
13289
|
+
const tail = 'call' === entry.kind ? '\\s*\\(' : '\\s*\\.\\s*[A-Za-z_$]';
|
|
13290
|
+
const memberRe = new RegExp(`\\b(?:chrome|browser)\\s*\\.\\s*${entry.api}\\s*\\.\\s*${entry.member}(?![\\w$])${tail}`);
|
|
12781
13291
|
return memberRe.test(source);
|
|
12782
13292
|
}
|
|
13293
|
+
function scanTargets(manifestVersion, engine) {
|
|
13294
|
+
const targets = geckoUnsupportedApis(manifestVersion, engine).map((api)=>({
|
|
13295
|
+
key: api,
|
|
13296
|
+
api,
|
|
13297
|
+
test: (text)=>usesGeckoUnsupportedApi(text, api, engine)
|
|
13298
|
+
}));
|
|
13299
|
+
if ('webkit' !== engine) return targets;
|
|
13300
|
+
for (const entry of webkitMemberEntries)targets.push({
|
|
13301
|
+
key: `${entry.api}.${entry.member}`,
|
|
13302
|
+
api: entry.api,
|
|
13303
|
+
member: entry.member,
|
|
13304
|
+
test: (text)=>usesWebkitUnsupportedMember(text, entry)
|
|
13305
|
+
});
|
|
13306
|
+
return targets;
|
|
13307
|
+
}
|
|
12783
13308
|
const EMITTED_SCRIPT_RE = /\.[cm]?js$/;
|
|
12784
13309
|
const MAX_SOURCE_BYTES = 1048576;
|
|
12785
13310
|
const MAX_ASSET_BYTES = 16777216;
|
|
@@ -12817,8 +13342,8 @@ function emittedFilesOf(compilation, module) {
|
|
|
12817
13342
|
return;
|
|
12818
13343
|
}
|
|
12819
13344
|
}
|
|
12820
|
-
function findGeckoUnsupportedApiUses(compilation, manifestVersion) {
|
|
12821
|
-
const
|
|
13345
|
+
function findGeckoUnsupportedApiUses(compilation, manifestVersion, engine = 'gecko', requireEmittedEvidence = false) {
|
|
13346
|
+
const targets = scanTargets(manifestVersion, engine);
|
|
12822
13347
|
const emitted = readEmittedScripts(compilation);
|
|
12823
13348
|
const explained = new Set();
|
|
12824
13349
|
const uses = new Map();
|
|
@@ -12832,20 +13357,23 @@ function findGeckoUnsupportedApiUses(compilation, manifestVersion) {
|
|
|
12832
13357
|
const resource = scannableSourcePath(module.resource);
|
|
12833
13358
|
if (!resource) continue;
|
|
12834
13359
|
const source = readProjectSource(resource);
|
|
12835
|
-
if (void 0 !== source) for (const
|
|
12836
|
-
const key = `${
|
|
12837
|
-
if (uses.has(key) || !
|
|
13360
|
+
if (void 0 !== source) for (const target of targets){
|
|
13361
|
+
const key = `${target.key}\0${resource}`;
|
|
13362
|
+
if (uses.has(key) || !target.test(source)) continue;
|
|
12838
13363
|
const files = emittedFilesOf(compilation, outer);
|
|
12839
13364
|
if (files) {
|
|
12840
13365
|
const carrying = files.filter((file)=>{
|
|
12841
13366
|
const text = emitted.get(file);
|
|
12842
|
-
return void 0 !== text &&
|
|
13367
|
+
return void 0 !== text && target.test(text);
|
|
12843
13368
|
});
|
|
12844
13369
|
if (!carrying.length) continue;
|
|
12845
|
-
for (const file of carrying)explained.add(`${
|
|
12846
|
-
}
|
|
13370
|
+
for (const file of carrying)explained.add(`${target.key}\0${file}`);
|
|
13371
|
+
} else if (requireEmittedEvidence) continue;
|
|
12847
13372
|
uses.set(key, {
|
|
12848
|
-
api,
|
|
13373
|
+
api: target.api,
|
|
13374
|
+
...target.member ? {
|
|
13375
|
+
member: target.member
|
|
13376
|
+
} : {},
|
|
12849
13377
|
file: resource,
|
|
12850
13378
|
emitted: false
|
|
12851
13379
|
});
|
|
@@ -12855,10 +13383,13 @@ function findGeckoUnsupportedApiUses(compilation, manifestVersion) {
|
|
|
12855
13383
|
if (!compilation.chunkGraph) return [
|
|
12856
13384
|
...uses.values()
|
|
12857
13385
|
];
|
|
12858
|
-
for (const [name, text] of emitted)for (const
|
|
12859
|
-
const key = `${
|
|
12860
|
-
if (!explained.has(key) &&
|
|
12861
|
-
api,
|
|
13386
|
+
for (const [name, text] of emitted)for (const target of targets){
|
|
13387
|
+
const key = `${target.key}\0${name}`;
|
|
13388
|
+
if (!explained.has(key) && target.test(text)) uses.set(key, {
|
|
13389
|
+
api: target.api,
|
|
13390
|
+
...target.member ? {
|
|
13391
|
+
member: target.member
|
|
13392
|
+
} : {},
|
|
12862
13393
|
file: name,
|
|
12863
13394
|
emitted: true
|
|
12864
13395
|
});
|
|
@@ -12880,16 +13411,25 @@ function relativeToProject(projectPath, file) {
|
|
|
12880
13411
|
}
|
|
12881
13412
|
return __rspack_external_node_path_806ed179.relative(projectPath, file) || file;
|
|
12882
13413
|
}
|
|
12883
|
-
function reportGeckoUnsupportedApis(compilation, compiler, browser, manifest, projectPath) {
|
|
12884
|
-
|
|
12885
|
-
if (!
|
|
13414
|
+
function reportGeckoUnsupportedApis(compilation, compiler, browser, manifest, projectPath, reported) {
|
|
13415
|
+
const engine = isGeckoBasedBrowser(String(browser)) ? 'gecko' : isWebkitBasedBrowser(String(browser)) ? 'webkit' : void 0;
|
|
13416
|
+
if (!engine) return;
|
|
13417
|
+
const isProduction = 'production' === compiler.options.mode;
|
|
13418
|
+
if (!isProduction && 'webkit' !== engine) return;
|
|
12886
13419
|
try {
|
|
12887
|
-
const uses = findGeckoUnsupportedApiUses(compilation, manifest.manifest_version);
|
|
13420
|
+
const uses = findGeckoUnsupportedApiUses(compilation, manifest.manifest_version, engine, !isProduction);
|
|
12888
13421
|
for (const use of uses){
|
|
12889
13422
|
const label = use.emitted ? use.file : relativeToProject(projectPath, use.file);
|
|
12890
|
-
|
|
13423
|
+
if (!isProduction && reported) {
|
|
13424
|
+
const signature = `${use.api}.${use.member || ''}\0${label}`;
|
|
13425
|
+
if (reported.has(signature)) continue;
|
|
13426
|
+
reported.add(signature);
|
|
13427
|
+
}
|
|
13428
|
+
const memberEntry = use.member ? webkitMemberByKey.get(`${use.api}.${use.member}`) : void 0;
|
|
13429
|
+
const webkitMessage = 'webkit' !== engine || memberEntry ? void 0 : webkitUnsupportedApis[use.api];
|
|
13430
|
+
const text = memberEntry ? safariMemberUnsupported(label, memberEntry.api, memberEntry.member, memberEntry.kind) : webkitMessage ? webkitMessage(label) : 'sidePanel' === use.api ? geckoSidePanelUnsupported(label) : geckoActionUnsupportedOnMv2(label);
|
|
12891
13431
|
const warn = new core_WebpackError(text);
|
|
12892
|
-
warn.name = 'GeckoUnsupportedApiWarning';
|
|
13432
|
+
warn.name = 'webkit' === engine ? 'SafariUnsupportedApiWarning' : 'GeckoUnsupportedApiWarning';
|
|
12893
13433
|
warn.file = label;
|
|
12894
13434
|
compilation.warnings.push(warn);
|
|
12895
13435
|
}
|
|
@@ -12899,6 +13439,7 @@ class UpdateManifest {
|
|
|
12899
13439
|
manifestPath;
|
|
12900
13440
|
browser;
|
|
12901
13441
|
reportedFatalFixes = new Set();
|
|
13442
|
+
reportedUnsupportedApis = new Set();
|
|
12902
13443
|
constructor(options){
|
|
12903
13444
|
this.manifestPath = options.manifestPath;
|
|
12904
13445
|
this.browser = options.browser || 'chrome';
|
|
@@ -12929,10 +13470,19 @@ class UpdateManifest {
|
|
|
12929
13470
|
const dropReason = pageActionDropReason(forBrowser, this.browser);
|
|
12930
13471
|
if (dropReason) reportToCompilation(compilation, compiler, 'conflicts' === dropReason ? pageActionDroppedForBrowserAction(String(this.browser)) : pageActionNotSupportedByBrowser(String(this.browser)), 'warning', 'manifest.json');
|
|
12931
13472
|
if (hasMv2SandboxPolicy(forBrowser)) reportToCompilation(compilation, compiler, mv2SandboxPolicyDropped(String(this.browser)), 'warning', 'manifest.json');
|
|
13473
|
+
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');
|
|
12932
13474
|
const projectPath = compiler.options.context || __rspack_external_node_path_806ed179.dirname(this.manifestPath);
|
|
12933
13475
|
let patchedManifest = buildCanonicalManifest(this.manifestPath, manifest, this.browser, projectPath);
|
|
13476
|
+
if ('production' === compiler.options.mode) {
|
|
13477
|
+
const edgeKey = dropEdgeStoreKey(patchedManifest, this.browser);
|
|
13478
|
+
if (edgeKey.dropped) {
|
|
13479
|
+
patchedManifest = edgeKey.manifest;
|
|
13480
|
+
reportToCompilation(compilation, compiler, edgeStoreKeyDropped(String(this.browser)), 'warning', 'manifest.json');
|
|
13481
|
+
}
|
|
13482
|
+
}
|
|
12934
13483
|
patchedManifest = patchGeckoBackground(patchedManifest, this.browser);
|
|
12935
13484
|
patchedManifest = patchChromiumBackground(patchedManifest, this.browser);
|
|
13485
|
+
patchedManifest = patchWebkitBackground(patchedManifest, this.browser);
|
|
12936
13486
|
patchedManifest = patchChromiumThemeColors(patchedManifest, this.browser);
|
|
12937
13487
|
const overrides = getManifestOverrides(this.manifestPath, manifest, projectPath);
|
|
12938
13488
|
if ('development' === compiler.options.mode) {
|
|
@@ -12972,7 +13522,7 @@ class UpdateManifest {
|
|
|
12972
13522
|
warn.file = 'manifest.json';
|
|
12973
13523
|
compilation.warnings.push(warn);
|
|
12974
13524
|
}
|
|
12975
|
-
reportGeckoUnsupportedApis(compilation, compiler, this.browser, patchedManifest, projectPath);
|
|
13525
|
+
reportGeckoUnsupportedApis(compilation, compiler, this.browser, patchedManifest, projectPath, this.reportedUnsupportedApis);
|
|
12976
13526
|
const source = JSON.stringify(patchedManifest, null, 2);
|
|
12977
13527
|
const rawSource = new core_sources.RawSource(source);
|
|
12978
13528
|
setCurrentManifestContent(compilation, source);
|
|
@@ -14279,7 +14829,8 @@ function webpackConfig(projectStructure, devOptions) {
|
|
|
14279
14829
|
]
|
|
14280
14830
|
},
|
|
14281
14831
|
node: {
|
|
14282
|
-
__dirname: false
|
|
14832
|
+
__dirname: false,
|
|
14833
|
+
global: false
|
|
14283
14834
|
},
|
|
14284
14835
|
resolveLoader: {
|
|
14285
14836
|
modules: [
|