extension-develop 3.0.0-next.9 → 3.1.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -16
- package/dist/215.js +546 -0
- package/dist/323.js +425 -0
- package/dist/329.js +9094 -0
- package/dist/419.js +44 -0
- package/dist/552.js +54 -0
- package/dist/814.js +127125 -0
- package/dist/814.js.LICENSE.txt +24 -0
- package/dist/928.js +416 -0
- package/dist/add-centralized-logger-script-background.js +3 -3
- package/dist/add-centralized-logger-script-content.js +4 -4
- package/dist/add-centralized-logger-script.js +18 -27
- package/dist/add-hmr-accept-code.js +3 -3
- package/dist/content-script-wrapper.js +114 -32
- package/dist/ensure-hmr-for-scripts.js +3 -3
- package/dist/extension-js-devtools/chrome/assets/logo.7dc70d61.png +0 -0
- package/dist/extension-js-devtools/chrome/background/service_worker.js +26 -0
- package/dist/extension-js-devtools/chrome/chrome_url_overrides/newtab.html +23 -0
- package/dist/extension-js-devtools/chrome/devtools/index.html +12 -0
- package/dist/extension-js-devtools/chrome/devtools/index.js +1 -0
- package/dist/extension-js-devtools/chrome/icons/logo.png +0 -0
- package/dist/extension-js-devtools/chrome/logo.png +0 -0
- package/dist/extension-js-devtools/chrome/manifest.json +44 -0
- package/dist/extension-js-devtools/chrome/pages/centralized-logger.css +2 -0
- package/dist/extension-js-devtools/chrome/pages/centralized-logger.html +12 -0
- package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +16 -0
- package/dist/extension-js-devtools/chrome/pages/welcome.css +2 -0
- package/dist/extension-js-devtools/chrome/pages/welcome.html +11 -0
- package/dist/extension-js-devtools/chrome/pages/welcome.js +21 -0
- package/dist/extension-js-devtools/chrome/scripts/logger-client.js +1 -0
- package/dist/extension-js-devtools/chromium/assets/logo.7dc70d61.png +0 -0
- package/dist/extension-js-devtools/chromium/background/service_worker.js +26 -0
- package/dist/extension-js-devtools/chromium/chrome_url_overrides/newtab.html +23 -0
- package/dist/extension-js-devtools/chromium/devtools/index.html +12 -0
- package/dist/extension-js-devtools/chromium/devtools/index.js +1 -0
- package/dist/extension-js-devtools/chromium/icons/logo.png +0 -0
- package/dist/extension-js-devtools/chromium/logo.png +0 -0
- package/dist/extension-js-devtools/chromium/manifest.json +44 -0
- package/dist/extension-js-devtools/chromium/pages/centralized-logger.css +2 -0
- package/dist/extension-js-devtools/chromium/pages/centralized-logger.html +12 -0
- package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +16 -0
- package/dist/extension-js-devtools/chromium/pages/welcome.css +2 -0
- package/dist/extension-js-devtools/chromium/pages/welcome.html +11 -0
- package/dist/extension-js-devtools/chromium/pages/welcome.js +21 -0
- package/dist/extension-js-devtools/chromium/scripts/logger-client.js +1 -0
- package/dist/extension-js-devtools/edge/assets/logo.7dc70d61.png +0 -0
- package/dist/extension-js-devtools/edge/background/service_worker.js +26 -0
- package/dist/extension-js-devtools/edge/chrome_url_overrides/newtab.html +23 -0
- package/dist/extension-js-devtools/edge/devtools/index.html +12 -0
- package/dist/extension-js-devtools/edge/devtools/index.js +1 -0
- package/dist/extension-js-devtools/edge/icons/logo.png +0 -0
- package/dist/extension-js-devtools/edge/logo.png +0 -0
- package/dist/extension-js-devtools/edge/manifest.json +44 -0
- package/dist/extension-js-devtools/edge/pages/centralized-logger.css +2 -0
- package/dist/extension-js-devtools/edge/pages/centralized-logger.html +12 -0
- package/dist/extension-js-devtools/edge/pages/centralized-logger.js +16 -0
- package/dist/extension-js-devtools/edge/pages/welcome.css +2 -0
- package/dist/extension-js-devtools/edge/pages/welcome.html +11 -0
- package/dist/extension-js-devtools/edge/pages/welcome.js +21 -0
- package/dist/extension-js-devtools/edge/scripts/logger-client.js +1 -0
- package/dist/extension-js-devtools/firefox/assets/logo.7dc70d61.png +0 -0
- package/dist/extension-js-devtools/firefox/background/scripts.js +26 -0
- package/dist/extension-js-devtools/firefox/devtools/index.html +12 -0
- package/dist/extension-js-devtools/firefox/devtools/index.js +1 -0
- package/dist/extension-js-devtools/firefox/icons/logo.png +0 -0
- package/dist/extension-js-devtools/firefox/logo.png +0 -0
- package/dist/extension-js-devtools/firefox/manifest.json +30 -0
- package/dist/extension-js-devtools/firefox/pages/centralized-logger.css +2 -0
- package/dist/extension-js-devtools/firefox/pages/centralized-logger.html +12 -0
- package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +16 -0
- package/dist/extension-js-devtools/firefox/pages/welcome.css +2 -0
- package/dist/extension-js-devtools/firefox/pages/welcome.html +11 -0
- package/dist/extension-js-devtools/firefox/pages/welcome.js +21 -0
- package/dist/extension-js-devtools/firefox/scripts/logger-client.js +1 -0
- package/dist/extension-js-theme/chrome/manifest.json +65 -0
- package/dist/extension-js-theme/chromium/manifest.json +65 -0
- package/dist/extension-js-theme/edge/manifest.json +65 -0
- package/dist/extension-js-theme/firefox/manifest.json +6 -0
- package/dist/main-world-bridge.js +109 -0
- package/dist/minimum-chromium-file.js +2 -3
- package/dist/minimum-firefox-file.js +2 -3
- package/dist/minimum-script-file.js +25 -1
- package/dist/module.js +4774 -13450
- package/dist/resolve-paths-loader.js +61 -102
- package/dist/warn-no-default-export.js +173 -10
- package/package.json +55 -49
- package/dist/930.js +0 -44
package/README.md
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
[npm-version-image]: https://img.shields.io/npm/v/extension-develop.svg?color=0971fe
|
|
2
2
|
[npm-version-url]: https://www.npmjs.com/package/extension-develop
|
|
3
|
-
[downloads-image]: https://img.shields.io/npm/dm/extension-develop.svg?color=
|
|
4
|
-
[downloads-url]: https://npmjs.
|
|
5
|
-
[
|
|
6
|
-
[
|
|
3
|
+
[npm-downloads-image]: https://img.shields.io/npm/dm/extension-develop.svg?color=0971fe
|
|
4
|
+
[npm-downloads-url]: https://www.npmjs.com/package/extension-develop
|
|
5
|
+
[powered-image]: https://img.shields.io/badge/Powered%20by-Extension.js-0971fe
|
|
6
|
+
[powered-url]: https://extension.js.org
|
|
7
|
+
[action-image]: https://github.com/extension-js/extension.js/actions/workflows/ci.yml/badge.svg?branch=main&color=0971fe
|
|
8
|
+
[action-url]: https://github.com/extension-js/extension.js/actions
|
|
7
9
|
|
|
8
|
-
[![
|
|
10
|
+
[![Powered by Extension.js][powered-image]][powered-url]
|
|
9
11
|
|
|
10
|
-
# extension-develop
|
|
12
|
+
# extension-develop [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![workflow][action-image]][action-url]
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
Develop, build, preview, and package [Extension.js](https://extension.js.org) projects.
|
|
13
15
|
|
|
14
16
|
This package powers Extension.js during local development and production builds. It provides the commands and build plugins that compile your extension, run it in browsers, and produce distributable artifacts.
|
|
15
17
|
|
|
@@ -68,18 +70,18 @@ run()
|
|
|
68
70
|
- Zipping: distribution and/or source packages (respects `.gitignore`)
|
|
69
71
|
- Auto-install of missing dependencies and package manager detection
|
|
70
72
|
- Type generation for TS projects via `extension-env.d.ts`
|
|
71
|
-
- User config via `extension.config.(js|mjs)` for commands, browser
|
|
73
|
+
- User config via `extension.config.(js|mjs)` for commands, browser start, unified logger defaults, and webpack config hooks
|
|
72
74
|
- Managed dependency guard to avoid conflicts
|
|
73
75
|
|
|
74
76
|
## Commands
|
|
75
77
|
|
|
76
|
-
| Name | Summary
|
|
77
|
-
| ------- |
|
|
78
|
-
| dev | - Starts a local development server with live reload/HMR<br/>- Auto-installs dependencies if missing<br/>- Generates TypeScript shim types (`extension-env.d.ts`) when applicable<br/>-
|
|
79
|
-
| build | - Production build using the webpack/Rspack plugin stack<br/>- Cleans `dist/<browser>` before emitting<br/>- Optional packaging: distribution zip and/or source zip<br/>- Merges user config; excludes browser runners during compilation
|
|
80
|
-
| start | - Runs a silent production build, then
|
|
81
|
-
| preview | -
|
|
82
|
-
| cleanup | - Removes orphaned browser instances and temporary profiles created during development
|
|
78
|
+
| Name | Summary |
|
|
79
|
+
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
80
|
+
| dev | - Starts a local development server with live reload/HMR<br/>- Auto-installs dependencies if missing<br/>- Generates TypeScript shim types (`extension-env.d.ts`) when applicable<br/>- Runs a target browser with an isolated/stable profile |
|
|
81
|
+
| build | - Production build using the webpack/Rspack plugin stack<br/>- Cleans `dist/<browser>` before emitting<br/>- Optional packaging: distribution zip and/or source zip<br/>- Merges user config; excludes browser runners during compilation |
|
|
82
|
+
| start | - Runs a silent production build, then runs preview from `dist/<browser>`<br/>- Mirrors the runtime environment of shipped output |
|
|
83
|
+
| preview | - Runs the extension for manual testing without dev server<br/>- Uses `dist/<browser>` when present, otherwise uses the project directory<br/>- Preserves production settings; only browser runners are applied |
|
|
84
|
+
| cleanup | - Removes orphaned browser instances and temporary profiles created during development |
|
|
83
85
|
|
|
84
86
|
## Command options
|
|
85
87
|
|
|
@@ -158,10 +160,48 @@ Options accepted by each command. Values shown are typical types or enumerations
|
|
|
158
160
|
- Supported sections:
|
|
159
161
|
- config(config: Configuration): mutate the assembled Rspack config. Supports a function or a plain object. When an object is provided, it is deep‑merged on top of the assembled config.
|
|
160
162
|
- commands.dev | .build | .start | .preview: per‑command options (browser, profile, binaries, flags, preferences, unified logger defaults, packaging). These defaults are applied for all respective commands.
|
|
161
|
-
- browser.chrome | .firefox | .edge | .chromium-based | .gecko-based:
|
|
163
|
+
- browser.chrome | .firefox | .edge | .chromium-based | .gecko-based: start flags, excluded flags, preferences, binaries, and profile reuse (persistProfile).
|
|
164
|
+
- extensions: load-only companion extensions (unpacked dirs) loaded alongside your extension in dev/preview/start.
|
|
165
|
+
- Example: { dir: "./extensions" } loads every "./extensions/\*" folder that contains a manifest.json.
|
|
162
166
|
- Precedence when composing options: browser._ → commands._ → CLI flags. CLI flags always win over config defaults.
|
|
167
|
+
- Browser key aliases when resolving `browser.*` from `extension.config.*`:
|
|
168
|
+
- When the runtime asks for `chromium`, `loadBrowserConfig` prefers `browser.chromium` and then falls back to `browser['chromium-based']`.
|
|
169
|
+
- When the runtime asks for `chromium-based`, it prefers `browser['chromium-based']` and then `browser.chromium`.
|
|
170
|
+
- When the runtime asks for `firefox`, it prefers `browser.firefox` and then `browser['gecko-based']`.
|
|
171
|
+
- When the runtime asks for `gecko-based`, it prefers `browser['gecko-based']` and then `browser.firefox`.
|
|
163
172
|
- When detected, a one‑time notice is printed to indicate config is active.
|
|
164
173
|
|
|
174
|
+
### Companion extensions (load-only)
|
|
175
|
+
|
|
176
|
+
Use this when you have other unpacked extensions you want loaded alongside your main extension during `dev`, `start`, and `preview`.
|
|
177
|
+
|
|
178
|
+
- **What it loads**: directories that contain a `manifest.json` at their root (unpacked extension roots).
|
|
179
|
+
- **How they’re loaded**: they’re appended into the browser runner’s `--load-extension` list (Chromium) / addon install list (Firefox) **before** your extension. Your extension is always loaded last for precedence.
|
|
180
|
+
- **Discovery**:
|
|
181
|
+
- `extensions.dir`: scans one level deep (e.g. `./extensions/*/manifest.json`)
|
|
182
|
+
- `extensions.paths`: explicit directories (absolute or relative to the project root)
|
|
183
|
+
- **Overrides**: top-level `extensions` applies to all commands, but `commands.<cmd>.extensions` overrides it for that command.
|
|
184
|
+
- **Invalid entries**: ignored. In author mode (`EXTENSION_AUTHOR_MODE=true`) we print a warning if `extensions` is configured but nothing resolves.
|
|
185
|
+
|
|
186
|
+
Example:
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
// extension.config.mjs
|
|
190
|
+
export default {
|
|
191
|
+
// Applies to dev/start/preview unless overridden per-command
|
|
192
|
+
extensions: {
|
|
193
|
+
dir: './extensions',
|
|
194
|
+
paths: ['./vendor/some-unpacked-extension']
|
|
195
|
+
},
|
|
196
|
+
commands: {
|
|
197
|
+
dev: {
|
|
198
|
+
// Override only for dev
|
|
199
|
+
extensions: ['./extensions/debug-helper']
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
165
205
|
### Environment variables in `extension.config.*`
|
|
166
206
|
|
|
167
207
|
- `extension.config.*` runs in a Node context during command startup.
|
package/dist/215.js
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.ids = [
|
|
3
|
+
"215"
|
|
4
|
+
];
|
|
5
|
+
exports.modules = {
|
|
6
|
+
"./webpack/plugin-browsers/run-chromium/chromium-source-inspection/cdp-client.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
7
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
8
|
+
n: ()=>CDPClient
|
|
9
|
+
});
|
|
10
|
+
var external_ws_ = __webpack_require__("ws");
|
|
11
|
+
var external_ws_default = /*#__PURE__*/ __webpack_require__.n(external_ws_);
|
|
12
|
+
var messages = __webpack_require__("./webpack/plugin-browsers/browsers-lib/messages.ts");
|
|
13
|
+
async function getExtensionInfo(cdp, extensionId) {
|
|
14
|
+
return await cdp.sendCommand('Extensions.getExtensionInfo', {
|
|
15
|
+
extensionId
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async function loadUnpackedExtension(cdp, absPath) {
|
|
19
|
+
const response = await cdp.sendCommand('Extensions.loadUnpacked', {
|
|
20
|
+
extensionPath: absPath,
|
|
21
|
+
options: {
|
|
22
|
+
failOnError: false
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return String(response?.extensionId || '');
|
|
26
|
+
}
|
|
27
|
+
async function unloadExtension(cdp, extensionId) {
|
|
28
|
+
try {
|
|
29
|
+
await cdp.sendCommand('Extensions.unload', {
|
|
30
|
+
extensionId
|
|
31
|
+
});
|
|
32
|
+
return true;
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
var discovery = __webpack_require__("./webpack/plugin-browsers/run-chromium/chromium-source-inspection/discovery.ts");
|
|
38
|
+
function establishBrowserConnection(url, isDev, onMessage, onRejectPending) {
|
|
39
|
+
return new Promise((resolve, reject)=>{
|
|
40
|
+
const ws = new (external_ws_default())(url);
|
|
41
|
+
ws.on('open', ()=>{
|
|
42
|
+
if (isDev) console.log(messages.F1E());
|
|
43
|
+
resolve(ws);
|
|
44
|
+
});
|
|
45
|
+
ws.on('message', (data)=>{
|
|
46
|
+
onMessage(data.toString());
|
|
47
|
+
});
|
|
48
|
+
ws.on('error', (error)=>{
|
|
49
|
+
if (isDev) console.error(messages.fRy(error.message));
|
|
50
|
+
onRejectPending(error.message);
|
|
51
|
+
reject(error);
|
|
52
|
+
});
|
|
53
|
+
ws.on('close', ()=>{
|
|
54
|
+
if (isDev) console.log(messages.hE8());
|
|
55
|
+
onRejectPending('CDP connection closed');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function mergeShadowIntoDocument(mainHTML, shadowContent) {
|
|
60
|
+
try {
|
|
61
|
+
if (!mainHTML) return '';
|
|
62
|
+
const hasRoot = /<div id=(["'])extension-root\1/i.test(mainHTML);
|
|
63
|
+
if (hasRoot) {
|
|
64
|
+
const emptyRoot = /<div id=(["'])extension-root\1[^>]*><\/div>/i;
|
|
65
|
+
const replacedEmpty = mainHTML.replace(emptyRoot, `<div id="extension-root">${shadowContent}</div>`);
|
|
66
|
+
if (replacedEmpty !== mainHTML) return replacedEmpty;
|
|
67
|
+
return mainHTML.replace(/<div id=(["'])extension-root\1[^>]*>[\s\S]*?<\/div>/i, `<div id="extension-root">${shadowContent}</div>`);
|
|
68
|
+
}
|
|
69
|
+
const hostOpen = /(<[^>]*data-extension-root=(["'])true\2[^>]*>)/i;
|
|
70
|
+
if (hostOpen.test(mainHTML)) return mainHTML.replace(hostOpen, `$1<div id="extension-root">${shadowContent}</div>`);
|
|
71
|
+
if (/<\/body>/i.test(mainHTML)) return mainHTML.replace(/<\/body>/i, `<div id="extension-root">${shadowContent}</div></body>`);
|
|
72
|
+
return `${mainHTML}\n<div id="extension-root">${shadowContent}</div>`;
|
|
73
|
+
} catch {
|
|
74
|
+
return mainHTML;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function getPageHTML(cdp, sessionId) {
|
|
78
|
+
try {
|
|
79
|
+
await cdp.evaluate(sessionId, 'document.title');
|
|
80
|
+
} catch {}
|
|
81
|
+
const mainHTMLRaw = await cdp.evaluate(sessionId, `(() => {
|
|
82
|
+
try {
|
|
83
|
+
const serialize = () => {
|
|
84
|
+
const doctype = document.doctype
|
|
85
|
+
const dt = doctype
|
|
86
|
+
? '<!DOCTYPE '
|
|
87
|
+
+ doctype.name
|
|
88
|
+
+ (doctype.publicId ? ' PUBLIC "' + doctype.publicId + '"' : '')
|
|
89
|
+
+ (doctype.systemId ? ' "' + doctype.systemId + '"' : '')
|
|
90
|
+
+ '>'
|
|
91
|
+
: ''
|
|
92
|
+
return dt + '\n' + document.documentElement.outerHTML
|
|
93
|
+
}
|
|
94
|
+
return serialize()
|
|
95
|
+
} catch (e) {
|
|
96
|
+
return ''
|
|
97
|
+
}
|
|
98
|
+
})()`);
|
|
99
|
+
const mainHTML = 'string' == typeof mainHTMLRaw ? mainHTMLRaw : String(mainHTMLRaw || '');
|
|
100
|
+
try {
|
|
101
|
+
const mergedHtmlRaw = await cdp.evaluate(sessionId, `(() => { try {
|
|
102
|
+
var cloned = document.documentElement.cloneNode(true);
|
|
103
|
+
var host = cloned.querySelector('#extension-root,[data-extension-root="true"]');
|
|
104
|
+
if (!host) {
|
|
105
|
+
var body = cloned.querySelector('body') || cloned;
|
|
106
|
+
var newRoot = document.createElement('div');
|
|
107
|
+
newRoot.id='extension-root';
|
|
108
|
+
body.appendChild(newRoot);
|
|
109
|
+
host = newRoot;
|
|
110
|
+
}
|
|
111
|
+
var s = new XMLSerializer();
|
|
112
|
+
var shadow = '';
|
|
113
|
+
try {
|
|
114
|
+
var liveHost = document.querySelector('[data-extension-root=\"true\"]') || document.getElementById('extension-root');
|
|
115
|
+
if (liveHost && liveHost.shadowRoot) {
|
|
116
|
+
shadow = Array.from(liveHost.shadowRoot.childNodes).map(function(n){
|
|
117
|
+
try { return s.serializeToString(n) } catch(e){ return '' }
|
|
118
|
+
}).join('');
|
|
119
|
+
}
|
|
120
|
+
} catch(e) {}
|
|
121
|
+
try { host.innerHTML = shadow; } catch(e) {}
|
|
122
|
+
var doctype = document.doctype;
|
|
123
|
+
var dt = doctype ? '<!DOCTYPE ' + doctype.name + (doctype.publicId ? ' PUBLIC \"' + doctype.publicId + '\"' : '') + (doctype.systemId ? ' \"' + doctype.systemId + '\"' : '') + '>' : '';
|
|
124
|
+
return String(dt + '\\n' + (cloned.outerHTML || document.documentElement.outerHTML));
|
|
125
|
+
} catch(e) { try { return String(document.documentElement.outerHTML); } catch(_) { return '' } } })()`);
|
|
126
|
+
const mergedHtml = 'string' == typeof mergedHtmlRaw ? mergedHtmlRaw : String(mergedHtmlRaw || '');
|
|
127
|
+
if (mergedHtml && /<html[\s>]/i.test(mergedHtml)) return mergedHtml;
|
|
128
|
+
} catch {}
|
|
129
|
+
let shadowContent = '';
|
|
130
|
+
try {
|
|
131
|
+
shadowContent = await cdp.evaluate(sessionId, `(() => {
|
|
132
|
+
try {
|
|
133
|
+
const hosts = Array.from(document.querySelectorAll('[data-extension-root="true"]'));
|
|
134
|
+
if (!hosts.length) return '';
|
|
135
|
+
const preferMarkers = ['iskilar_box','content_script','content_title','js-probe'];
|
|
136
|
+
let firstNonEmpty = '';
|
|
137
|
+
for (const host of hosts) {
|
|
138
|
+
try {
|
|
139
|
+
const sr = host && host.shadowRoot;
|
|
140
|
+
if (!sr) continue;
|
|
141
|
+
const html = String(sr.innerHTML || '');
|
|
142
|
+
if (html && html.length) {
|
|
143
|
+
if (preferMarkers.some((m) => html.includes(m))) return html;
|
|
144
|
+
if (!firstNonEmpty) firstNonEmpty = html;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const parts = Array.from(sr.children)
|
|
149
|
+
.map((n) => (n && n.outerHTML) ? String(n.outerHTML) : '')
|
|
150
|
+
.join('');
|
|
151
|
+
if (parts && parts.length) {
|
|
152
|
+
if (preferMarkers.some((m) => parts.includes(m))) return parts;
|
|
153
|
+
if (!firstNonEmpty) firstNonEmpty = parts;
|
|
154
|
+
}
|
|
155
|
+
} catch { /* ignore */ }
|
|
156
|
+
} catch { /* ignore */ }
|
|
157
|
+
}
|
|
158
|
+
return firstNonEmpty || '';
|
|
159
|
+
} catch { return '' }
|
|
160
|
+
})()`);
|
|
161
|
+
} catch {}
|
|
162
|
+
if (shadowContent) try {
|
|
163
|
+
const sc = 'string' == typeof shadowContent ? shadowContent : String(shadowContent || '');
|
|
164
|
+
return mergeShadowIntoDocument(mainHTML, sc);
|
|
165
|
+
} catch {}
|
|
166
|
+
return mainHTML;
|
|
167
|
+
}
|
|
168
|
+
async function waitForLoadEvent(cdp, sessionId) {
|
|
169
|
+
return new Promise((resolve)=>{
|
|
170
|
+
let resolved = false;
|
|
171
|
+
const listener = (data)=>{
|
|
172
|
+
try {
|
|
173
|
+
const message = JSON.parse(data);
|
|
174
|
+
if ('Page.loadEventFired' === message.method && message.sessionId === sessionId && !resolved) {
|
|
175
|
+
resolved = true;
|
|
176
|
+
resolve();
|
|
177
|
+
}
|
|
178
|
+
} catch {}
|
|
179
|
+
};
|
|
180
|
+
const clientWithHandle = cdp;
|
|
181
|
+
const original = clientWithHandle.handleMessage.bind(cdp);
|
|
182
|
+
clientWithHandle.handleMessage = (data)=>{
|
|
183
|
+
original(data);
|
|
184
|
+
listener(data);
|
|
185
|
+
};
|
|
186
|
+
setTimeout(()=>{
|
|
187
|
+
if (!resolved) {
|
|
188
|
+
resolved = true;
|
|
189
|
+
console.log(messages.Qiq());
|
|
190
|
+
resolve();
|
|
191
|
+
}
|
|
192
|
+
clientWithHandle.handleMessage = original;
|
|
193
|
+
}, 2000);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
async function waitForContentScriptInjection(cdp, sessionId) {
|
|
197
|
+
const deadline = Date.now() + 30000;
|
|
198
|
+
const started = Date.now();
|
|
199
|
+
while(Date.now() < deadline){
|
|
200
|
+
try {
|
|
201
|
+
const injected = await cdp.evaluate(sessionId, `(() => { try {
|
|
202
|
+
const hosts = Array.from(document.querySelectorAll('[data-extension-root="true"]'));
|
|
203
|
+
if (!hosts.length) return false;
|
|
204
|
+
const markers = ['iskilar_box','content_script','content_title','js-probe'];
|
|
205
|
+
for (const h of hosts) {
|
|
206
|
+
try {
|
|
207
|
+
const sr = h && h.shadowRoot;
|
|
208
|
+
if (!sr) continue;
|
|
209
|
+
const html = String(sr.innerHTML||'');
|
|
210
|
+
if (html.length > 0) return true;
|
|
211
|
+
if (markers.some((m) => html.includes(m))) return true;
|
|
212
|
+
try {
|
|
213
|
+
const parts = Array.from(sr.children).map((n) => (n && n.outerHTML) ? String(n.outerHTML) : '').join('');
|
|
214
|
+
if (parts && parts.length) return true;
|
|
215
|
+
if (markers.some((m) => parts.includes(m))) return true;
|
|
216
|
+
} catch { /* ignore */ }
|
|
217
|
+
} catch { /* ignore */ }
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
} catch { return false } })()`);
|
|
221
|
+
if (Boolean(injected)) return;
|
|
222
|
+
} catch {}
|
|
223
|
+
const elapsed = Date.now() - started;
|
|
224
|
+
const delay = elapsed < 2000 ? 150 : 500;
|
|
225
|
+
await new Promise((r)=>setTimeout(r, delay));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function _define_property(obj, key, value) {
|
|
229
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
230
|
+
value: value,
|
|
231
|
+
enumerable: true,
|
|
232
|
+
configurable: true,
|
|
233
|
+
writable: true
|
|
234
|
+
});
|
|
235
|
+
else obj[key] = value;
|
|
236
|
+
return obj;
|
|
237
|
+
}
|
|
238
|
+
class CDPClient {
|
|
239
|
+
isDev() {
|
|
240
|
+
return 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
241
|
+
}
|
|
242
|
+
async connect() {
|
|
243
|
+
return new Promise(async (resolve, reject)=>{
|
|
244
|
+
try {
|
|
245
|
+
this.targetWebSocketUrl = await (0, discovery.N)(this.host, this.port, this.isDev());
|
|
246
|
+
this.ws = await establishBrowserConnection(this.targetWebSocketUrl, this.isDev(), (data)=>this.handleMessage(data), (reason)=>{
|
|
247
|
+
this.pendingRequests.forEach(({ reject }, id)=>{
|
|
248
|
+
try {
|
|
249
|
+
reject(new Error(reason));
|
|
250
|
+
} catch (error) {
|
|
251
|
+
if (this.isDev()) {
|
|
252
|
+
const err = error;
|
|
253
|
+
console.warn(messages.r0s(String(err.message || err)));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
this.pendingRequests.delete(id);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
if (this.isDev()) console.log(messages.M3V(this.host, this.port));
|
|
260
|
+
resolve();
|
|
261
|
+
} catch (error) {
|
|
262
|
+
const err = error;
|
|
263
|
+
reject(new Error(`Failed to connect to CDP: ${err.message || err}`));
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
disconnect() {
|
|
268
|
+
if (this.ws) {
|
|
269
|
+
try {
|
|
270
|
+
this.ws.close();
|
|
271
|
+
} catch {}
|
|
272
|
+
this.ws = null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
onProtocolEvent(handler) {
|
|
276
|
+
this.eventCallback = handler;
|
|
277
|
+
}
|
|
278
|
+
handleMessage(data) {
|
|
279
|
+
try {
|
|
280
|
+
const message = JSON.parse(data);
|
|
281
|
+
if (message.id) {
|
|
282
|
+
const pending = this.pendingRequests.get(message.id);
|
|
283
|
+
if (pending) {
|
|
284
|
+
this.pendingRequests.delete(message.id);
|
|
285
|
+
if (message.error) pending.reject(new Error(JSON.stringify(message.error)));
|
|
286
|
+
else pending.resolve(message.result);
|
|
287
|
+
}
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if ('Target.attachedToTarget' === message.method) {
|
|
291
|
+
const params = message.params || {};
|
|
292
|
+
if (this.isDev()) console.log(messages.p8m(String(params.sessionId || ''), String(params.targetInfo?.type || '')));
|
|
293
|
+
}
|
|
294
|
+
if (this.eventCallback) this.eventCallback(message);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (this.isDev()) {
|
|
297
|
+
const err = error;
|
|
298
|
+
console.warn(messages.xxG(String(err.message || err)));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
async sendCommand(method, params = {}, sessionId) {
|
|
303
|
+
return new Promise((resolve, reject)=>{
|
|
304
|
+
if (!this.ws || this.ws.readyState !== external_ws_default().OPEN) return reject(new Error('WebSocket is not open'));
|
|
305
|
+
const id = ++this.messageId;
|
|
306
|
+
const message = {
|
|
307
|
+
id,
|
|
308
|
+
method,
|
|
309
|
+
params
|
|
310
|
+
};
|
|
311
|
+
if (sessionId) message.sessionId = sessionId;
|
|
312
|
+
try {
|
|
313
|
+
this.pendingRequests.set(id, {
|
|
314
|
+
resolve,
|
|
315
|
+
reject
|
|
316
|
+
});
|
|
317
|
+
this.ws.send(JSON.stringify(message));
|
|
318
|
+
} catch (error) {
|
|
319
|
+
this.pendingRequests.delete(id);
|
|
320
|
+
reject(error);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
async getTargets() {
|
|
325
|
+
const response = await this.sendCommand('Target.getTargets');
|
|
326
|
+
return response?.targetInfos || [];
|
|
327
|
+
}
|
|
328
|
+
async getBrowserVersion() {
|
|
329
|
+
const response = await this.sendCommand('Browser.getVersion');
|
|
330
|
+
return response || {};
|
|
331
|
+
}
|
|
332
|
+
async attachToTarget(targetId) {
|
|
333
|
+
const response = await this.sendCommand('Target.attachToTarget', {
|
|
334
|
+
targetId,
|
|
335
|
+
flatten: true
|
|
336
|
+
});
|
|
337
|
+
return response.sessionId || '';
|
|
338
|
+
}
|
|
339
|
+
async enableAutoAttach() {
|
|
340
|
+
await this.sendCommand('Target.setAutoAttach', {
|
|
341
|
+
autoAttach: true,
|
|
342
|
+
waitForDebuggerOnStart: false,
|
|
343
|
+
flatten: true
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
async enableRuntimeAndLog(sessionId) {
|
|
347
|
+
await this.sendCommand('Log.enable', {}, sessionId);
|
|
348
|
+
if (sessionId) await this.sendCommand('Runtime.enable', {}, sessionId);
|
|
349
|
+
}
|
|
350
|
+
async navigate(sessionId, url) {
|
|
351
|
+
await this.sendCommand('Page.navigate', {
|
|
352
|
+
url
|
|
353
|
+
}, sessionId);
|
|
354
|
+
}
|
|
355
|
+
async createTarget(url) {
|
|
356
|
+
const res = await this.sendCommand('Target.createTarget', {
|
|
357
|
+
url
|
|
358
|
+
});
|
|
359
|
+
return String(res?.targetId || '');
|
|
360
|
+
}
|
|
361
|
+
async activateTarget(targetId) {
|
|
362
|
+
await this.sendCommand('Target.activateTarget', {
|
|
363
|
+
targetId
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
async waitForLoadEvent(sessionId) {
|
|
367
|
+
return waitForLoadEvent(this, sessionId);
|
|
368
|
+
}
|
|
369
|
+
async waitForContentScriptInjection(sessionId) {
|
|
370
|
+
return waitForContentScriptInjection(this, sessionId);
|
|
371
|
+
}
|
|
372
|
+
async evaluate(sessionId, expression) {
|
|
373
|
+
const response = await this.sendCommand('Runtime.evaluate', {
|
|
374
|
+
expression,
|
|
375
|
+
returnByValue: true
|
|
376
|
+
}, sessionId);
|
|
377
|
+
return response.result?.value;
|
|
378
|
+
}
|
|
379
|
+
async getPageHTML(sessionId) {
|
|
380
|
+
return getPageHTML(this, sessionId);
|
|
381
|
+
}
|
|
382
|
+
async closeTarget(targetId) {
|
|
383
|
+
await this.sendCommand('Target.closeTarget', {
|
|
384
|
+
targetId
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
async forceReloadExtension(extensionId) {
|
|
388
|
+
try {
|
|
389
|
+
await this.sendCommand('Extensions.reload', {
|
|
390
|
+
extensionId,
|
|
391
|
+
forceReload: true
|
|
392
|
+
});
|
|
393
|
+
return true;
|
|
394
|
+
} catch (error) {
|
|
395
|
+
const attempts = 3;
|
|
396
|
+
for(let i = 0; i < attempts; i++){
|
|
397
|
+
try {
|
|
398
|
+
const ok = await this.reloadExtensionViaTargetEval(extensionId);
|
|
399
|
+
if (ok) return true;
|
|
400
|
+
} catch {}
|
|
401
|
+
await new Promise((r)=>setTimeout(r, 150 * (i + 1)));
|
|
402
|
+
}
|
|
403
|
+
console.warn(messages.ccn(extensionId, error.message || String(error)));
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
async getExtensionInfo(extensionId) {
|
|
408
|
+
try {
|
|
409
|
+
return await getExtensionInfo(this, extensionId);
|
|
410
|
+
} catch (error) {
|
|
411
|
+
throw new Error(messages.Z5i(extensionId, error.message));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
async reloadExtensionViaTargetEval(extensionId) {
|
|
415
|
+
try {
|
|
416
|
+
const targets = await this.getTargets();
|
|
417
|
+
const preferredOrder = [
|
|
418
|
+
'service_worker',
|
|
419
|
+
'background_page',
|
|
420
|
+
'worker'
|
|
421
|
+
];
|
|
422
|
+
for (const type of preferredOrder){
|
|
423
|
+
const t = (targets || []).find((t)=>{
|
|
424
|
+
const url = String(t?.url || '');
|
|
425
|
+
const tt = String(t?.type || '');
|
|
426
|
+
return tt === type && url.startsWith(`chrome-extension://${extensionId}/`);
|
|
427
|
+
});
|
|
428
|
+
if (!t) continue;
|
|
429
|
+
const targetId = t?.targetId;
|
|
430
|
+
if (targetId) try {
|
|
431
|
+
const sessionId = await this.attachToTarget(targetId);
|
|
432
|
+
await this.sendCommand('Runtime.enable', {}, sessionId);
|
|
433
|
+
await this.sendCommand('Runtime.evaluate', {
|
|
434
|
+
expression: 'chrome && chrome.runtime && chrome.runtime.reload && chrome.runtime.reload()'
|
|
435
|
+
}, sessionId);
|
|
436
|
+
return true;
|
|
437
|
+
} catch {}
|
|
438
|
+
}
|
|
439
|
+
return false;
|
|
440
|
+
} catch {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
async loadUnpackedExtension(path) {
|
|
445
|
+
try {
|
|
446
|
+
return await loadUnpackedExtension(this, path);
|
|
447
|
+
} catch (error) {
|
|
448
|
+
throw new Error(messages.xlM(path, error.message));
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async unloadExtension(extensionId) {
|
|
452
|
+
try {
|
|
453
|
+
return await unloadExtension(this, extensionId);
|
|
454
|
+
} catch (error) {
|
|
455
|
+
console.error(messages.yEr(extensionId, error.message));
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
constructor(port = 9222, host = '127.0.0.1'){
|
|
460
|
+
_define_property(this, "port", void 0);
|
|
461
|
+
_define_property(this, "host", void 0);
|
|
462
|
+
_define_property(this, "ws", null);
|
|
463
|
+
_define_property(this, "targetWebSocketUrl", null);
|
|
464
|
+
_define_property(this, "eventCallback", void 0);
|
|
465
|
+
_define_property(this, "messageId", 0);
|
|
466
|
+
_define_property(this, "pendingRequests", new Map());
|
|
467
|
+
this.port = port;
|
|
468
|
+
this.host = host;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
"./webpack/plugin-browsers/run-chromium/chromium-source-inspection/discovery.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
473
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
474
|
+
N: ()=>discoverWebSocketDebuggerUrl,
|
|
475
|
+
z: ()=>checkChromeRemoteDebugging
|
|
476
|
+
});
|
|
477
|
+
var http__rspack_import_0 = __webpack_require__("http");
|
|
478
|
+
var net__rspack_import_1 = __webpack_require__("net");
|
|
479
|
+
var _browsers_lib_messages__rspack_import_2 = __webpack_require__("./webpack/plugin-browsers/browsers-lib/messages.ts");
|
|
480
|
+
async function getJson(host, port, path) {
|
|
481
|
+
return new Promise((resolve, reject)=>{
|
|
482
|
+
const req = http__rspack_import_0.request({
|
|
483
|
+
hostname: host,
|
|
484
|
+
port,
|
|
485
|
+
path,
|
|
486
|
+
method: 'GET'
|
|
487
|
+
}, (res)=>{
|
|
488
|
+
let data = '';
|
|
489
|
+
res.on('data', (chunk)=>data += chunk);
|
|
490
|
+
res.on('end', ()=>{
|
|
491
|
+
try {
|
|
492
|
+
resolve(JSON.parse(data));
|
|
493
|
+
} catch (e) {
|
|
494
|
+
reject(new Error(`Failed to parse ${path}: ${e}`));
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
req.on('error', (err)=>reject(err));
|
|
499
|
+
req.end();
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
async function discoverWebSocketDebuggerUrl(host, port, isDev) {
|
|
503
|
+
try {
|
|
504
|
+
const version = await getJson(host, port, '/json/version');
|
|
505
|
+
const wsUrl = 'string' == typeof version?.webSocketDebuggerUrl ? version.webSocketDebuggerUrl : void 0;
|
|
506
|
+
if (wsUrl) {
|
|
507
|
+
if (isDev) console.log(_browsers_lib_messages__rspack_import_2.Ter());
|
|
508
|
+
return wsUrl;
|
|
509
|
+
}
|
|
510
|
+
} catch (error) {
|
|
511
|
+
if (isDev) console.warn('[CDP] Failed to read /json/version:', String(error?.message || error));
|
|
512
|
+
}
|
|
513
|
+
const targets = await getJson(host, port, '/json');
|
|
514
|
+
if (isDev) console.log(_browsers_lib_messages__rspack_import_2.FFz((targets || []).length || 0));
|
|
515
|
+
const pageTarget = (targets || []).find((target)=>{
|
|
516
|
+
const type = String(target?.type || '');
|
|
517
|
+
const ws = 'string' == typeof target?.webSocketDebuggerUrl ? target.webSocketDebuggerUrl : '';
|
|
518
|
+
return 'page' === type && ws;
|
|
519
|
+
});
|
|
520
|
+
const pageWs = 'string' == typeof pageTarget?.webSocketDebuggerUrl ? pageTarget.webSocketDebuggerUrl : '';
|
|
521
|
+
if (pageWs) {
|
|
522
|
+
if (isDev) console.log(_browsers_lib_messages__rspack_import_2.Ter());
|
|
523
|
+
return pageWs;
|
|
524
|
+
}
|
|
525
|
+
throw new Error('No CDP WebSocket URL available');
|
|
526
|
+
}
|
|
527
|
+
async function checkChromeRemoteDebugging(port = 9222) {
|
|
528
|
+
return new Promise((resolve)=>{
|
|
529
|
+
const socket = new net__rspack_import_1.Socket();
|
|
530
|
+
socket.on('connect', ()=>{
|
|
531
|
+
socket.destroy();
|
|
532
|
+
resolve(true);
|
|
533
|
+
});
|
|
534
|
+
socket.on('error', ()=>{
|
|
535
|
+
resolve(false);
|
|
536
|
+
});
|
|
537
|
+
socket.on('timeout', ()=>{
|
|
538
|
+
socket.destroy();
|
|
539
|
+
resolve(false);
|
|
540
|
+
});
|
|
541
|
+
socket.setTimeout(2000);
|
|
542
|
+
socket.connect(port, 'localhost');
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
};
|