extension-develop 3.18.3 → 3.18.4-canary.321.403955d
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/0~dev-server.mjs +6 -2
- package/dist/0~rslib-runtime.mjs +1 -17
- package/dist/0~rspack-config.mjs +261 -47
- package/dist/946.mjs +544 -534
- package/dist/962.mjs +4 -2
- package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/chrome/devtools/index.js +1 -1
- package/dist/extension-js-devtools/chrome/manifest.json +3 -3
- package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/chromium/devtools/index.js +1 -1
- package/dist/extension-js-devtools/chromium/manifest.json +3 -3
- package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/edge/devtools/index.js +1 -1
- package/dist/extension-js-devtools/edge/manifest.json +3 -3
- package/dist/extension-js-devtools/extension-js/chrome/events.ndjson +2 -2
- package/dist/extension-js-devtools/extension-js/chrome/ready.json +5 -5
- package/dist/extension-js-devtools/extension-js/chromium/events.ndjson +2 -2
- package/dist/extension-js-devtools/extension-js/chromium/ready.json +5 -5
- package/dist/extension-js-devtools/extension-js/edge/events.ndjson +2 -2
- package/dist/extension-js-devtools/extension-js/edge/ready.json +5 -5
- package/dist/extension-js-devtools/extension-js/firefox/events.ndjson +2 -2
- package/dist/extension-js-devtools/extension-js/firefox/ready.json +5 -5
- package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/firefox/devtools/index.js +1 -1
- package/dist/extension-js-theme/extension-js/chrome/events.ndjson +2 -2
- package/dist/extension-js-theme/extension-js/chrome/ready.json +5 -5
- package/dist/extension-js-theme/extension-js/chromium/events.ndjson +2 -2
- package/dist/extension-js-theme/extension-js/chromium/ready.json +5 -5
- package/dist/extension-js-theme/extension-js/edge/events.ndjson +2 -2
- package/dist/extension-js-theme/extension-js/edge/ready.json +5 -5
- package/dist/extension-js-theme/extension-js/firefox/events.ndjson +4 -4
- package/dist/extension-js-theme/extension-js/firefox/ready.json +5 -5
- package/dist/feature-scripts-content-script-wrapper.js +7 -37
- package/dist/feature-scripts-content-script-wrapper.mjs +7 -37
- package/package.json +2 -7
- package/dist/resolve-paths-loader.js +0 -1300
- package/dist/resolve-paths-loader.mjs +0 -1300
package/dist/0~dev-server.mjs
CHANGED
|
@@ -569,11 +569,15 @@ class BridgeBroker {
|
|
|
569
569
|
reload: this.allowControl,
|
|
570
570
|
open: this.allowControl ? isFirefox ? [
|
|
571
571
|
'popup',
|
|
572
|
-
'options'
|
|
572
|
+
'options',
|
|
573
|
+
'action',
|
|
574
|
+
'command'
|
|
573
575
|
] : [
|
|
574
576
|
'popup',
|
|
575
577
|
'options',
|
|
576
|
-
'sidebar'
|
|
578
|
+
'sidebar',
|
|
579
|
+
'action',
|
|
580
|
+
'command'
|
|
577
581
|
] : [],
|
|
578
582
|
deepDom: 'chromium' === this.engine
|
|
579
583
|
}
|
package/dist/0~rslib-runtime.mjs
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
|
-
var
|
|
3
|
-
var __webpack_module_cache__ = {};
|
|
4
|
-
function __webpack_require__(moduleId) {
|
|
5
|
-
var cachedModule = __webpack_module_cache__[moduleId];
|
|
6
|
-
if (void 0 !== cachedModule) return cachedModule.exports;
|
|
7
|
-
var module = __webpack_module_cache__[moduleId] = {
|
|
8
|
-
exports: {}
|
|
9
|
-
};
|
|
10
|
-
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
11
|
-
return module.exports;
|
|
12
|
-
}
|
|
13
|
-
__webpack_require__.m = __webpack_modules__;
|
|
2
|
+
var __webpack_require__ = {};
|
|
14
3
|
(()=>{
|
|
15
4
|
__webpack_require__.d = (exports, definition)=>{
|
|
16
5
|
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
|
|
@@ -19,11 +8,6 @@ __webpack_require__.m = __webpack_modules__;
|
|
|
19
8
|
});
|
|
20
9
|
};
|
|
21
10
|
})();
|
|
22
|
-
(()=>{
|
|
23
|
-
__webpack_require__.add = function(modules) {
|
|
24
|
-
Object.assign(__webpack_require__.m, modules);
|
|
25
|
-
};
|
|
26
|
-
})();
|
|
27
11
|
(()=>{
|
|
28
12
|
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
29
13
|
})();
|
package/dist/0~rspack-config.mjs
CHANGED
|
@@ -375,7 +375,9 @@ function getFilename(feature, filePath) {
|
|
|
375
375
|
'.js',
|
|
376
376
|
'.jsx',
|
|
377
377
|
'.tsx',
|
|
378
|
-
'.ts'
|
|
378
|
+
'.ts',
|
|
379
|
+
'.vue',
|
|
380
|
+
'.svelte'
|
|
379
381
|
].includes(entryExt)) fileOutputpath = fileOutputpath.replace(entryExt, '.js');
|
|
380
382
|
if ([
|
|
381
383
|
'.html',
|
|
@@ -817,6 +819,7 @@ function storage(manifest) {
|
|
|
817
819
|
};
|
|
818
820
|
}
|
|
819
821
|
const theme_getBasename = (filepath)=>__rspack_external_path.basename(filepath);
|
|
822
|
+
const rewriteThemeImage = (value)=>getFilename(`theme/images/${theme_getBasename(value)}`, value);
|
|
820
823
|
function theme(manifest) {
|
|
821
824
|
return manifest.theme && {
|
|
822
825
|
theme: {
|
|
@@ -824,7 +827,7 @@ function theme(manifest) {
|
|
|
824
827
|
...manifest.theme.images && {
|
|
825
828
|
images: Object.fromEntries(Object.entries(manifest.theme.images).map(([key, value])=>[
|
|
826
829
|
key,
|
|
827
|
-
|
|
830
|
+
Array.isArray(value) ? value.map(rewriteThemeImage) : rewriteThemeImage(value)
|
|
828
831
|
]))
|
|
829
832
|
}
|
|
830
833
|
}
|
|
@@ -851,16 +854,18 @@ function normalizeOutputPath(originalPath) {
|
|
|
851
854
|
}
|
|
852
855
|
function webAccessibleResources(manifest) {
|
|
853
856
|
if (!manifest.web_accessible_resources || !manifest.web_accessible_resources.length) return;
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
857
|
+
const mapResource = (resource)=>getFilename(normalizeOutputPath(resource), resource);
|
|
858
|
+
const entries = manifest.web_accessible_resources.map((entry)=>{
|
|
859
|
+
if ('string' == typeof entry) return mapResource(entry);
|
|
860
|
+
if (!entry || !Array.isArray(entry.resources)) return;
|
|
861
|
+
return {
|
|
858
862
|
...entry,
|
|
859
|
-
resources:
|
|
860
|
-
}
|
|
861
|
-
|
|
863
|
+
resources: entry.resources.map(mapResource)
|
|
864
|
+
};
|
|
865
|
+
}).filter((entry)=>void 0 !== entry);
|
|
866
|
+
if (0 === entries.length) return;
|
|
862
867
|
return {
|
|
863
|
-
web_accessible_resources:
|
|
868
|
+
web_accessible_resources: entries
|
|
864
869
|
};
|
|
865
870
|
}
|
|
866
871
|
function contentSecurityPolicy(manifest) {
|
|
@@ -2910,6 +2915,7 @@ class JsFrameworksPlugin {
|
|
|
2910
2915
|
issuerLayer: {
|
|
2911
2916
|
not: EXTENSIONJS_CONTENT_SCRIPT_LAYER
|
|
2912
2917
|
},
|
|
2918
|
+
type: "javascript/esm",
|
|
2913
2919
|
exclude: [
|
|
2914
2920
|
...swcRuleBase.exclude,
|
|
2915
2921
|
(resourcePath)=>isfeatureScriptsContentLike(resourcePath)
|
|
@@ -3108,6 +3114,25 @@ function purgeStaleHashedContentScripts(compilation, currentNames) {
|
|
|
3108
3114
|
}
|
|
3109
3115
|
} catch {}
|
|
3110
3116
|
}
|
|
3117
|
+
function isGeckoBrowser(browser) {
|
|
3118
|
+
const b = String(browser);
|
|
3119
|
+
return 'firefox' === b || b.includes('firefox') || b.includes('gecko');
|
|
3120
|
+
}
|
|
3121
|
+
function patchGeckoBackground(manifest, browser) {
|
|
3122
|
+
if (!isGeckoBrowser(browser)) return manifest;
|
|
3123
|
+
const background = manifest.background;
|
|
3124
|
+
if (!background || !background.service_worker || background.scripts) return manifest;
|
|
3125
|
+
const { service_worker, type, ...rest } = background;
|
|
3126
|
+
return {
|
|
3127
|
+
...manifest,
|
|
3128
|
+
background: {
|
|
3129
|
+
...rest,
|
|
3130
|
+
scripts: [
|
|
3131
|
+
service_worker
|
|
3132
|
+
]
|
|
3133
|
+
}
|
|
3134
|
+
};
|
|
3135
|
+
}
|
|
3111
3136
|
class UpdateManifest {
|
|
3112
3137
|
manifestPath;
|
|
3113
3138
|
browser;
|
|
@@ -3133,6 +3158,7 @@ class UpdateManifest {
|
|
|
3133
3158
|
if (compilation.errors.length > 0) return;
|
|
3134
3159
|
const manifest = getManifestContent(compilation, this.manifestPath);
|
|
3135
3160
|
let patchedManifest = buildCanonicalManifest(this.manifestPath, manifest, this.browser);
|
|
3161
|
+
patchedManifest = patchGeckoBackground(patchedManifest, this.browser);
|
|
3136
3162
|
const overrides = getManifestOverrides(this.manifestPath, manifest);
|
|
3137
3163
|
if ('development' === compiler.options.mode) patchedManifest = patchDevContentScriptManifestPaths(compilation, patchedManifest);
|
|
3138
3164
|
if ('development' === compiler.options.mode) {
|
|
@@ -3169,6 +3195,18 @@ function getSharedFor(compilation) {
|
|
|
3169
3195
|
}
|
|
3170
3196
|
return shared;
|
|
3171
3197
|
}
|
|
3198
|
+
function cleanMatches(matches) {
|
|
3199
|
+
return matches.map((match)=>{
|
|
3200
|
+
try {
|
|
3201
|
+
const url = new URL(match.replace(/^\*:\/\//, 'https://'));
|
|
3202
|
+
if (match.endsWith(url.pathname)) return `${match.substring(0, match.length - url.pathname.length)}/*`;
|
|
3203
|
+
if ('/' === url.pathname) return `${match}/*`;
|
|
3204
|
+
return match;
|
|
3205
|
+
} catch {
|
|
3206
|
+
return match;
|
|
3207
|
+
}
|
|
3208
|
+
});
|
|
3209
|
+
}
|
|
3172
3210
|
function warFieldError(filePath, opts) {
|
|
3173
3211
|
const displayPath = opts?.overrideNotFoundPath || filePath;
|
|
3174
3212
|
const lines = [];
|
|
@@ -3179,6 +3217,10 @@ function warFieldError(filePath, opts) {
|
|
|
3179
3217
|
lines.push(`To reference files in ${pintor.yellow('public/')}, use a leading '/' (e.g. ${pintor.yellow('/open-panel.gif')}). These resolve from the built extension root.`);
|
|
3180
3218
|
lines.push('');
|
|
3181
3219
|
lines.push(`Fix: Add the file to ${pintor.yellow('public/')} or update the path to the correct '/...' location.`);
|
|
3220
|
+
} else if (opts?.sourceSibling) {
|
|
3221
|
+
lines.push(`Found ${pintor.yellow(opts.sourceSibling)}, but web_accessible_resources entries are copied as-is, not compiled.`);
|
|
3222
|
+
lines.push('');
|
|
3223
|
+
lines.push(`Fix: Import the file from a script so it gets bundled, or move a prebuilt copy to ${pintor.yellow('public/')} and reference it with a leading '/'.`);
|
|
3182
3224
|
} else {
|
|
3183
3225
|
lines.push("Relative paths must point to a real source file so the build can emit it.");
|
|
3184
3226
|
lines.push('');
|
|
@@ -3189,6 +3231,16 @@ function warFieldError(filePath, opts) {
|
|
|
3189
3231
|
lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(displayPath)}`);
|
|
3190
3232
|
return lines.join('\n');
|
|
3191
3233
|
}
|
|
3234
|
+
function warStringEntryInMv3(entry) {
|
|
3235
|
+
const lines = [];
|
|
3236
|
+
lines.push(`Check the ${pintor.yellow('web_accessible_resources')} field in your ${pintor.yellow('manifest.json')} file.`);
|
|
3237
|
+
lines.push(`Manifest V3 requires object entries with ${pintor.yellow('resources')} and ${pintor.yellow('matches')} (or ${pintor.yellow('extension_ids')}). Plain string entries are the Manifest V2 format and Chrome rejects them at load time.`);
|
|
3238
|
+
lines.push('');
|
|
3239
|
+
lines.push(`Fix: Wrap it like ${pintor.yellow(`{"resources": ["${entry}"], "matches": ["<all_urls>"]}`)} with the matches your pages need.`);
|
|
3240
|
+
lines.push('');
|
|
3241
|
+
lines.push(`${pintor.red('INVALID MV3 ENTRY')} ${pintor.underline(entry)}`);
|
|
3242
|
+
return lines.join('\n');
|
|
3243
|
+
}
|
|
3192
3244
|
function warInvalidMatchPattern(pattern) {
|
|
3193
3245
|
const lines = [];
|
|
3194
3246
|
lines.push(`Check the ${pintor.yellow('web_accessible_resources')} field in your ${pintor.yellow('manifest.json')} file.`);
|
|
@@ -3229,6 +3281,33 @@ function emitFileAsAsset(compilation, absPath) {
|
|
|
3229
3281
|
compilation.fileDependencies.add(absPath);
|
|
3230
3282
|
return unixify(outName);
|
|
3231
3283
|
}
|
|
3284
|
+
function findSourceSibling(absOutputPath) {
|
|
3285
|
+
const candidatesByExt = {
|
|
3286
|
+
'.js': [
|
|
3287
|
+
'.ts',
|
|
3288
|
+
'.tsx',
|
|
3289
|
+
'.jsx',
|
|
3290
|
+
'.vue',
|
|
3291
|
+
'.svelte'
|
|
3292
|
+
],
|
|
3293
|
+
'.css': [
|
|
3294
|
+
'.scss',
|
|
3295
|
+
'.sass',
|
|
3296
|
+
'.less'
|
|
3297
|
+
],
|
|
3298
|
+
'.html': [
|
|
3299
|
+
'.njk',
|
|
3300
|
+
'.nunjucks'
|
|
3301
|
+
]
|
|
3302
|
+
};
|
|
3303
|
+
const ext = __rspack_external_path.extname(absOutputPath);
|
|
3304
|
+
const sourceExts = candidatesByExt[ext];
|
|
3305
|
+
if (!sourceExts) return;
|
|
3306
|
+
for (const sourceExt of sourceExts){
|
|
3307
|
+
const candidate = absOutputPath.slice(0, -ext.length) + sourceExt;
|
|
3308
|
+
if (__rspack_external_fs.existsSync(candidate)) return candidate;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3232
3311
|
function isFirefox(browser) {
|
|
3233
3312
|
return !!browser && browser.toLowerCase().includes('firefox');
|
|
3234
3313
|
}
|
|
@@ -3264,30 +3343,33 @@ function resolveUserDeclaredWAR(compilation, manifestPath, manifest, browser) {
|
|
|
3264
3343
|
v2,
|
|
3265
3344
|
v3
|
|
3266
3345
|
};
|
|
3267
|
-
const
|
|
3346
|
+
const isMv2 = 3 !== manifestObj.manifest_version;
|
|
3268
3347
|
const manifestDir = __rspack_external_path.dirname(manifestPath);
|
|
3269
3348
|
const projectPath = compilation.options?.context || manifestDir;
|
|
3270
|
-
const pushResource = (matches, resource)=>{
|
|
3271
|
-
if (
|
|
3349
|
+
const pushResource = (matches, resource, extra)=>{
|
|
3350
|
+
if (isMv2) return void v2.add(resource);
|
|
3272
3351
|
const key = (matches || []).join(',');
|
|
3273
3352
|
let group = v3.find((g)=>g.matches.join(',') === key);
|
|
3274
|
-
if (
|
|
3353
|
+
if (group) {
|
|
3354
|
+
if (extra && !group.extra) group.extra = extra;
|
|
3355
|
+
} else {
|
|
3275
3356
|
group = {
|
|
3276
3357
|
matches: matches || [],
|
|
3277
|
-
resources: new Set()
|
|
3358
|
+
resources: new Set(),
|
|
3359
|
+
extra
|
|
3278
3360
|
};
|
|
3279
3361
|
v3.push(group);
|
|
3280
3362
|
}
|
|
3281
3363
|
group.resources.add(resource);
|
|
3282
3364
|
};
|
|
3283
|
-
const handleOne = (matches, res)=>{
|
|
3365
|
+
const handleOne = (matches, res, extra)=>{
|
|
3284
3366
|
compilation.errors = compilation.errors || [];
|
|
3285
3367
|
compilation.warnings = compilation.warnings || [];
|
|
3286
3368
|
const normalizedOutput = normalizeManifestOutputPath(res);
|
|
3287
3369
|
const publicCandidate = __rspack_external_path.join(projectPath, 'public', normalizedOutput);
|
|
3288
|
-
if (__rspack_external_fs.existsSync(publicCandidate)) return void pushResource(matches, normalizedOutput);
|
|
3370
|
+
if (__rspack_external_fs.existsSync(publicCandidate)) return void pushResource(matches, normalizedOutput, extra);
|
|
3289
3371
|
__rspack_external_path.isAbsolute(res) || __rspack_external_path.join(manifestDir, isPublicRootLike(res) ? toPublicOutput(res) : res);
|
|
3290
|
-
if (/[*?\[\]{}]/.test(res)) return void pushResource(matches, res);
|
|
3372
|
+
if (/[*?\[\]{}]/.test(res)) return void pushResource(matches, res, extra);
|
|
3291
3373
|
if (isPublicRootLike(res)) {
|
|
3292
3374
|
const output = normalizeManifestOutputPath(res);
|
|
3293
3375
|
const publicAbs = __rspack_external_path.join(projectPath, 'public', output);
|
|
@@ -3318,7 +3400,7 @@ function resolveUserDeclaredWAR(compilation, manifestPath, manifest, browser) {
|
|
|
3318
3400
|
err.file = 'manifest.json';
|
|
3319
3401
|
compilation.warnings.push(err);
|
|
3320
3402
|
}
|
|
3321
|
-
pushResource(matches, output);
|
|
3403
|
+
pushResource(matches, output, extra);
|
|
3322
3404
|
return;
|
|
3323
3405
|
}
|
|
3324
3406
|
const abs = __rspack_external_path.isAbsolute(res) ? res : __rspack_external_path.join(manifestDir, res);
|
|
@@ -3330,46 +3412,47 @@ function resolveUserDeclaredWAR(compilation, manifestPath, manifest, browser) {
|
|
|
3330
3412
|
const assetEmitted = Boolean(asset2 && asset2.name === res) || __rspack_external_fs.existsSync(builtAbs);
|
|
3331
3413
|
if (__rspack_external_fs.existsSync(publicAbsMaybe) || assetEmitted) {
|
|
3332
3414
|
const output = toPublicOutput('/' + res);
|
|
3333
|
-
pushResource(matches, output);
|
|
3415
|
+
pushResource(matches, output, extra);
|
|
3334
3416
|
return;
|
|
3335
3417
|
}
|
|
3418
|
+
const sourceSibling = findSourceSibling(abs);
|
|
3336
3419
|
const msg = warFieldError(abs, {
|
|
3337
|
-
relativeRef: res
|
|
3420
|
+
relativeRef: res,
|
|
3421
|
+
sourceSibling: sourceSibling ? __rspack_external_path.relative(manifestDir, sourceSibling) : void 0
|
|
3338
3422
|
});
|
|
3339
3423
|
const warn = new core_WebpackError(msg);
|
|
3340
3424
|
warn.file = 'manifest.json';
|
|
3341
3425
|
warn.name = 'WARRelativeAssetMissing';
|
|
3342
3426
|
compilation.warnings.push(warn);
|
|
3343
|
-
pushResource(matches, res);
|
|
3344
3427
|
return;
|
|
3345
3428
|
}
|
|
3346
3429
|
const emitted = emitFileAsAsset(compilation, abs);
|
|
3347
|
-
pushResource(matches, emitted);
|
|
3430
|
+
pushResource(matches, emitted, extra);
|
|
3348
3431
|
};
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3432
|
+
war.forEach((entry)=>{
|
|
3433
|
+
if ('string' == typeof entry) {
|
|
3434
|
+
if (isMv2) return void handleOne(void 0, entry);
|
|
3435
|
+
const msg = warStringEntryInMv3(entry);
|
|
3436
|
+
const err = new core_WebpackError(msg);
|
|
3437
|
+
err.file = 'manifest.json';
|
|
3438
|
+
err.name = 'WARStringEntryInMv3';
|
|
3439
|
+
compilation.errors = compilation.errors || [];
|
|
3440
|
+
compilation.errors.push(err);
|
|
3441
|
+
return;
|
|
3442
|
+
}
|
|
3443
|
+
if (!entry || 'object' != typeof entry) return;
|
|
3444
|
+
const matches = entry.matches || [];
|
|
3352
3445
|
validateMatchesOrReport(compilation, matches, browser);
|
|
3353
|
-
if (!Array.isArray(
|
|
3354
|
-
|
|
3446
|
+
if (!Array.isArray(entry.resources)) return;
|
|
3447
|
+
const { resources: _resources, matches: _matches, ...extra } = entry;
|
|
3448
|
+
const extraFields = Object.keys(extra).length > 0 ? extra : void 0;
|
|
3449
|
+
entry.resources.forEach((res)=>handleOne(matches, res, extraFields));
|
|
3355
3450
|
});
|
|
3356
3451
|
return {
|
|
3357
3452
|
v2,
|
|
3358
3453
|
v3
|
|
3359
3454
|
};
|
|
3360
3455
|
}
|
|
3361
|
-
function cleanMatches(matches) {
|
|
3362
|
-
return matches.map((match)=>{
|
|
3363
|
-
try {
|
|
3364
|
-
const url = new URL(match.replace(/^\*:\/\//, 'https://'));
|
|
3365
|
-
if (match.endsWith(url.pathname)) return `${match.substring(0, match.length - url.pathname.length)}/*`;
|
|
3366
|
-
if ('/' === url.pathname) return `${match}/*`;
|
|
3367
|
-
return match;
|
|
3368
|
-
} catch {
|
|
3369
|
-
return match;
|
|
3370
|
-
}
|
|
3371
|
-
});
|
|
3372
|
-
}
|
|
3373
3456
|
function getAssetSource(compilation, filename) {
|
|
3374
3457
|
const byGet = 'function' == typeof compilation.getAsset ? compilation.getAsset(filename) : void 0;
|
|
3375
3458
|
const byAssets = !byGet && compilation.assets ? compilation.assets[filename] : void 0;
|
|
@@ -3434,6 +3517,7 @@ function mergeIntoV3Group(groups, normalizedMatches, resources, options) {
|
|
|
3434
3517
|
].sort()
|
|
3435
3518
|
});
|
|
3436
3519
|
}
|
|
3520
|
+
const assetScanCache = new WeakMap();
|
|
3437
3521
|
function isCanonicalContentScriptCss(resource) {
|
|
3438
3522
|
return /^content_scripts\/content-\d+\.css$/.test(resource);
|
|
3439
3523
|
}
|
|
@@ -3446,6 +3530,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
|
|
|
3446
3530
|
const canonicalManifest = getManifestContent(compilation, manifestPath);
|
|
3447
3531
|
const resolved = resolveUserDeclaredWAR(compilation, manifestPath, canonicalManifest, browser);
|
|
3448
3532
|
const webAccessibleResourcesV3 = 3 === canonicalManifest.manifest_version ? resolved.v3.map((g)=>({
|
|
3533
|
+
...g.extra || {},
|
|
3449
3534
|
matches: g.matches,
|
|
3450
3535
|
resources: Array.from(g.resources)
|
|
3451
3536
|
})) : [];
|
|
@@ -3455,11 +3540,17 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
|
|
|
3455
3540
|
const normalizedMatches = cleanMatches(matches);
|
|
3456
3541
|
const jsFiles = Array.isArray(contentScript.js) ? contentScript.js : [];
|
|
3457
3542
|
for (const jsFile of jsFiles){
|
|
3458
|
-
const
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3543
|
+
const assetForCache = 'function' == typeof compilation.getAsset ? compilation.getAsset(jsFile) : void 0;
|
|
3544
|
+
const cacheKey = assetForCache && 'object' == typeof assetForCache.source ? assetForCache.source : void 0;
|
|
3545
|
+
let filtered = cacheKey ? assetScanCache.get(cacheKey) : void 0;
|
|
3546
|
+
if (!filtered) {
|
|
3547
|
+
const source = getAssetSource(compilation, jsFile);
|
|
3548
|
+
if (!source) continue;
|
|
3549
|
+
const re = /assets\/[A-Za-z0-9._-]+/g;
|
|
3550
|
+
const found = source.match(re) || [];
|
|
3551
|
+
filtered = Array.from(new Set(found.filter((r)=>!r.endsWith('.js') && !r.endsWith('.map')))).sort();
|
|
3552
|
+
if (cacheKey) assetScanCache.set(cacheKey, filtered);
|
|
3553
|
+
}
|
|
3463
3554
|
if (0 !== filtered.length) mergeIntoV3Group(webAccessibleResourcesV3, normalizedMatches, filtered);
|
|
3464
3555
|
}
|
|
3465
3556
|
}
|
|
@@ -3513,7 +3604,8 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
|
|
|
3513
3604
|
const emittedCssUnderContentScripts = assetKeys.filter((k)=>k.startsWith("content_scripts/")).filter((k)=>k.endsWith('.css'));
|
|
3514
3605
|
const onDiskCssUnderContentScripts = [];
|
|
3515
3606
|
const outputPath = compilation.options.output?.path;
|
|
3516
|
-
|
|
3607
|
+
const isDevModeBuild = 'production' !== (compilation.options?.mode || 'development');
|
|
3608
|
+
if (outputPath && isDevModeBuild) try {
|
|
3517
3609
|
const csDir = __rspack_external_path.join(outputPath, "content_scripts");
|
|
3518
3610
|
if (__rspack_external_fs.existsSync(csDir)) {
|
|
3519
3611
|
for (const name of __rspack_external_fs.readdirSync(csDir))if (name.endsWith('.css')) onDiskCssUnderContentScripts.push(`content_scripts/${name}`);
|
|
@@ -3542,6 +3634,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
|
|
|
3542
3634
|
}
|
|
3543
3635
|
if (3 === canonicalManifest.manifest_version) {
|
|
3544
3636
|
if (webAccessibleResourcesV3.length > 0) canonicalManifest.web_accessible_resources = webAccessibleResourcesV3.map((entry)=>({
|
|
3637
|
+
...entry,
|
|
3545
3638
|
resources: Array.from(new Set(entry.resources)).sort(),
|
|
3546
3639
|
matches: Array.from(new Set(entry.matches)).sort()
|
|
3547
3640
|
})).sort((a, b)=>a.matches.join(',').localeCompare(b.matches.join(',')));
|
|
@@ -6647,6 +6740,44 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
6647
6740
|
var consoleRef = g.console || {};
|
|
6648
6741
|
g.__extjsBridgeProducerInstalled = true;
|
|
6649
6742
|
|
|
6743
|
+
// Capture extension event listeners at install time. The producer is
|
|
6744
|
+
// prepended to the background bundle, so these wraps run BEFORE user code
|
|
6745
|
+
// registers its listeners — letting the bridge replay them on demand. The
|
|
6746
|
+
// platform exposes no API to dispatch these events, and CDP attaches too
|
|
6747
|
+
// late to wrap addListener, so this is the only path. Replay invokes the
|
|
6748
|
+
// handler WITHOUT a user gesture, so the gesture-derived activeTab grant
|
|
6749
|
+
// does NOT apply (callers are told gesture:false). This is engine-agnostic:
|
|
6750
|
+
// it works on Chromium and Gecko because it only touches addListener.
|
|
6751
|
+
//
|
|
6752
|
+
// captureEvent transparently wraps addListener/removeListener (delegating to
|
|
6753
|
+
// the originals) and records callbacks into the sink array.
|
|
6754
|
+
function captureEvent(event, sink) {
|
|
6755
|
+
try {
|
|
6756
|
+
if (!event || typeof event.addListener !== "function") return;
|
|
6757
|
+
var origAdd = event.addListener.bind(event);
|
|
6758
|
+
event.addListener = function (cb) {
|
|
6759
|
+
if (typeof cb === "function" && sink.indexOf(cb) === -1) sink.push(cb);
|
|
6760
|
+
return origAdd(cb);
|
|
6761
|
+
};
|
|
6762
|
+
if (typeof event.removeListener === "function") {
|
|
6763
|
+
var origRemove = event.removeListener.bind(event);
|
|
6764
|
+
event.removeListener = function (cb) {
|
|
6765
|
+
var i = sink.indexOf(cb);
|
|
6766
|
+
if (i !== -1) sink.splice(i, 1);
|
|
6767
|
+
return origRemove(cb);
|
|
6768
|
+
};
|
|
6769
|
+
}
|
|
6770
|
+
} catch (e) { /* non-fatal: trigger falls back to its no-listener reply */ }
|
|
6771
|
+
}
|
|
6772
|
+
|
|
6773
|
+
// Use g.chrome (not the hoisted chrome var below) — this runs first.
|
|
6774
|
+
var actionClickedListeners = [];
|
|
6775
|
+
var commandListeners = [];
|
|
6776
|
+
if (g.chrome) {
|
|
6777
|
+
captureEvent(g.chrome.action && g.chrome.action.onClicked, actionClickedListeners);
|
|
6778
|
+
captureEvent(g.chrome.commands && g.chrome.commands.onCommand, commandListeners);
|
|
6779
|
+
}
|
|
6780
|
+
|
|
6650
6781
|
var LEVELS = ["log", "info", "warn", "error", "debug", "trace"];
|
|
6651
6782
|
var socket = null;
|
|
6652
6783
|
var open = false;
|
|
@@ -6751,6 +6882,42 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
6751
6882
|
}
|
|
6752
6883
|
if (op === "open") {
|
|
6753
6884
|
var surface = args.surface || ctx;
|
|
6885
|
+
// getPopup is promise-style on Gecko and (MV3) Chromium; fall back to
|
|
6886
|
+
// callback-style for older Chromium. Always resolves to a string.
|
|
6887
|
+
var getActionPopup = function (cb) {
|
|
6888
|
+
try {
|
|
6889
|
+
var r = chrome.action && chrome.action.getPopup && chrome.action.getPopup({});
|
|
6890
|
+
if (r && typeof r.then === "function") {
|
|
6891
|
+
r.then(function (p) { cb(p || ""); }, function () { cb(""); });
|
|
6892
|
+
return;
|
|
6893
|
+
}
|
|
6894
|
+
} catch (e) {}
|
|
6895
|
+
try { chrome.action.getPopup({}, function (p) { cb(p || ""); }); }
|
|
6896
|
+
catch (e) { cb(""); }
|
|
6897
|
+
};
|
|
6898
|
+
// Resolve the tab a replayed event should carry: an explicit args.tabId,
|
|
6899
|
+
// else the active tab of the focused window.
|
|
6900
|
+
var resolveActiveTab = function (a, cb) {
|
|
6901
|
+
if (a && typeof a.tabId === "number") {
|
|
6902
|
+
try { chrome.tabs.get(a.tabId, function (t) { cb(t || {id: a.tabId}); }); return; }
|
|
6903
|
+
catch (e) {}
|
|
6904
|
+
}
|
|
6905
|
+
try { chrome.tabs.query({active: true, lastFocusedWindow: true}, function (tabs) { cb((tabs && tabs[0]) || undefined); }); }
|
|
6906
|
+
catch (e) { cb(undefined); }
|
|
6907
|
+
};
|
|
6908
|
+
// Replaying a listener carries no user gesture, so activeTab is never
|
|
6909
|
+
// granted. Warn when the manifest declares it (handler will diverge
|
|
6910
|
+
// from a real click).
|
|
6911
|
+
var activeTabWarning = function () {
|
|
6912
|
+
try {
|
|
6913
|
+
var m = chrome.runtime.getManifest();
|
|
6914
|
+
var perms = (m && m.permissions) || [];
|
|
6915
|
+
if (perms.indexOf("activeTab") !== -1) {
|
|
6916
|
+
return "replayed without a user gesture: activeTab is NOT granted, so APIs that depend on it (scripting on the active tab, captureVisibleTab) behave differently than a real click";
|
|
6917
|
+
}
|
|
6918
|
+
} catch (e) {}
|
|
6919
|
+
return null;
|
|
6920
|
+
};
|
|
6754
6921
|
if (surface === "popup") {
|
|
6755
6922
|
if (chrome.action && chrome.action.openPopup) {
|
|
6756
6923
|
chrome.action.openPopup().then(function () { replyOk(cmdId, {opened: "popup"}); }, function (e) { replyErr(cmdId, "Unsupported", "openPopup: " + e); });
|
|
@@ -6764,6 +6931,47 @@ const BRIDGE_PRODUCER_SOURCE = `;(function () {
|
|
|
6764
6931
|
chrome.sidePanel.open({windowId: w.id}).then(function () { replyOk(cmdId, {opened: "sidebar"}); }, function (e) { replyErr(cmdId, "Unsupported", "sidePanel.open: " + e); });
|
|
6765
6932
|
});
|
|
6766
6933
|
} else { replyErr(cmdId, "Unsupported", "sidePanel not available (engine: " + engineName() + ")"); }
|
|
6934
|
+
} else if (surface === "action") {
|
|
6935
|
+
// Trigger the toolbar action. With a default_popup, clicking the icon
|
|
6936
|
+
// opens it (reuse openPopup). Without a popup, clicking fires
|
|
6937
|
+
// chrome.action.onClicked — we replay the listeners captured at install.
|
|
6938
|
+
if (chrome.action) {
|
|
6939
|
+
getActionPopup(function (popup) {
|
|
6940
|
+
if (popup) {
|
|
6941
|
+
try {
|
|
6942
|
+
chrome.action.openPopup().then(function () { replyOk(cmdId, {triggered: "popup"}); }, function (e) { replyErr(cmdId, "Unsupported", "openPopup: " + e); });
|
|
6943
|
+
} catch (e) { replyErr(cmdId, "Unsupported", "openPopup: " + e); }
|
|
6944
|
+
} else if (actionClickedListeners.length) {
|
|
6945
|
+
resolveActiveTab(args, function (tab) {
|
|
6946
|
+
var fired = 0;
|
|
6947
|
+
for (var i = 0; i < actionClickedListeners.length; i++) {
|
|
6948
|
+
try { actionClickedListeners[i](tab); fired++; } catch (e) {}
|
|
6949
|
+
}
|
|
6950
|
+
var reply = {triggered: "onClicked", listeners: fired, gesture: false};
|
|
6951
|
+
var warning = activeTabWarning();
|
|
6952
|
+
if (warning) reply.warning = warning;
|
|
6953
|
+
replyOk(cmdId, reply);
|
|
6954
|
+
});
|
|
6955
|
+
} else {
|
|
6956
|
+
replyErr(cmdId, "Unsupported", "action has no popup and no onClicked listener registered");
|
|
6957
|
+
}
|
|
6958
|
+
});
|
|
6959
|
+
} else { replyErr(cmdId, "Unsupported", "chrome.action not available (engine: " + engineName() + ")"); }
|
|
6960
|
+
} else if (surface === "command") {
|
|
6961
|
+
// Replay a captured chrome.commands.onCommand listener (keyboard
|
|
6962
|
+
// shortcut). Same no-gesture caveat as onClicked.
|
|
6963
|
+
var commandName = (args && args.name) || undefined;
|
|
6964
|
+
if (!commandListeners.length) {
|
|
6965
|
+
replyErr(cmdId, "Unsupported", "no chrome.commands.onCommand listener registered");
|
|
6966
|
+
} else {
|
|
6967
|
+
resolveActiveTab(args, function (tab) {
|
|
6968
|
+
var fired = 0;
|
|
6969
|
+
for (var i = 0; i < commandListeners.length; i++) {
|
|
6970
|
+
try { commandListeners[i](commandName, tab); fired++; } catch (e) {}
|
|
6971
|
+
}
|
|
6972
|
+
replyOk(cmdId, {triggered: "command", command: commandName || null, listeners: fired, gesture: false});
|
|
6973
|
+
});
|
|
6974
|
+
}
|
|
6767
6975
|
} else { replyErr(cmdId, "BadRequest", "unknown surface: " + surface); }
|
|
6768
6976
|
return;
|
|
6769
6977
|
}
|
|
@@ -7068,7 +7276,7 @@ function buildBridgeProducerSource(opts) {
|
|
|
7068
7276
|
if (!opts.controlPort || opts.controlPort < 1) return '';
|
|
7069
7277
|
return BRIDGE_PRODUCER_SOURCE.replace(/__EXTJS_CONTROL_PORT__/g, String(opts.controlPort)).replace(/__EXTJS_INSTANCE_ID__/g, String(opts.instanceId)).replace(/__EXTJS_CONTEXT__/g, String(opts.context || 'background'));
|
|
7070
7278
|
}
|
|
7071
|
-
const inject_bridge_producer_BACKGROUND_ASSET = /(^|\/)background\/(?:service_worker|
|
|
7279
|
+
const inject_bridge_producer_BACKGROUND_ASSET = /(^|\/)background\/(?:service_worker|scripts?)\.js$/i;
|
|
7072
7280
|
class InjectBridgeProducer {
|
|
7073
7281
|
apply(compiler) {
|
|
7074
7282
|
const controlPort = parseInt(String(process.env.EXTENSION_CONTROL_PORT || ''), 10);
|
|
@@ -8697,6 +8905,12 @@ function webpackConfig(projectStructure, devOptions) {
|
|
|
8697
8905
|
mode: devOptions.mode || 'development',
|
|
8698
8906
|
entry: {},
|
|
8699
8907
|
target: 'web',
|
|
8908
|
+
externals: [
|
|
8909
|
+
({ request }, callback)=>{
|
|
8910
|
+
if ('string' == typeof request && /^(chrome|moz)-extension:/i.test(request)) return callback(null, request, 'asset');
|
|
8911
|
+
callback();
|
|
8912
|
+
}
|
|
8913
|
+
],
|
|
8700
8914
|
context: packageJsonDir,
|
|
8701
8915
|
cache: false,
|
|
8702
8916
|
devtool: 'production' === (devOptions.mode || 'development') ? false : 3 === manifest.manifest_version ? 'cheap-source-map' : 'eval-cheap-source-map',
|