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