extension-develop 4.1.25-canary.408.177007 → 4.1.26
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/{731~0.mjs → 474~0.mjs} +52 -2
- package/dist/672~0.mjs +1 -2
- package/dist/832~0.mjs +14 -7
- package/dist/840~0.mjs +9 -3
- package/dist/950~0.mjs +8 -2
- package/dist/bridge.mjs +1 -0
- package/dist/dev-server/control-bridge/broker.d.ts +8 -2
- package/dist/dev-server/control-bridge/consumer-client.d.ts +1 -0
- package/dist/dev-server/control-bridge/contracts.d.ts +3 -2
- package/dist/dev-server/control-bridge/ws-control-server.d.ts +2 -0
- package/dist/dev-server/dev-middleware-body.d.ts +16 -0
- package/dist/dev-server/emulator-lane.d.ts +56 -0
- package/dist/dev-server/messages.d.ts +1 -0
- package/dist/dev-server~0.mjs +284 -13
- package/dist/feature-scripts-content-script-wrapper.js +1 -1
- package/dist/feature-scripts-content-script-wrapper.mjs +1 -1
- package/dist/lib/constants.d.ts +3 -0
- package/dist/lib/paths.d.ts +2 -2
- package/dist/plugin-browsers/index.d.ts +3 -0
- package/dist/plugin-playwright/index.d.ts +2 -1
- package/dist/plugin-web-extension/shared/omit-owned-pages.d.ts +2 -0
- package/dist/rspack-config~0.mjs +28 -9
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/dist/331~0.mjs +0 -45
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
|
-
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
3
2
|
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
3
|
+
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
4
|
+
__rspack_external_node_path_806ed179.join(process.cwd(), 'node_modules/extension-develop/dist/certs');
|
|
5
|
+
const CHROMIUM_BASED_BROWSERS = [
|
|
6
|
+
'chrome',
|
|
7
|
+
'edge',
|
|
8
|
+
'brave',
|
|
9
|
+
'opera',
|
|
10
|
+
'vivaldi',
|
|
11
|
+
'yandex'
|
|
12
|
+
];
|
|
13
|
+
const GECKO_BASED_BROWSERS = [
|
|
14
|
+
'firefox',
|
|
15
|
+
'waterfox',
|
|
16
|
+
'librewolf',
|
|
17
|
+
'zen',
|
|
18
|
+
'floorp'
|
|
19
|
+
];
|
|
20
|
+
const WEBKIT_BASED_BROWSERS = [
|
|
21
|
+
'safari'
|
|
22
|
+
];
|
|
23
|
+
const CHROMIUM_FAMILY_ALIASES = [
|
|
24
|
+
'chromium',
|
|
25
|
+
'chrome',
|
|
26
|
+
'edge',
|
|
27
|
+
'chromium-based'
|
|
28
|
+
];
|
|
29
|
+
const GECKO_FAMILY_ALIASES = [
|
|
30
|
+
'firefox',
|
|
31
|
+
'gecko-based'
|
|
32
|
+
];
|
|
33
|
+
const EMULATOR_BROWSER = 'chromium-emulator';
|
|
34
|
+
function isEmulatorLaneEnabled(env = process.env) {
|
|
35
|
+
const value = String(env.EXTENSION_EXPERIMENTAL_EMULATOR || '').trim().toLowerCase();
|
|
36
|
+
return '1' === value || 'true' === value;
|
|
37
|
+
}
|
|
38
|
+
function isEmulatorBrowser(browser) {
|
|
39
|
+
return browser === EMULATOR_BROWSER;
|
|
40
|
+
}
|
|
41
|
+
[
|
|
42
|
+
...CHROMIUM_BASED_BROWSERS,
|
|
43
|
+
...GECKO_BASED_BROWSERS
|
|
44
|
+
];
|
|
45
|
+
function isChromiumBasedBrowser(browser) {
|
|
46
|
+
return CHROMIUM_BASED_BROWSERS.includes(browser) || String(browser).includes('chromium');
|
|
47
|
+
}
|
|
48
|
+
function isGeckoBasedBrowser(browser) {
|
|
49
|
+
return GECKO_BASED_BROWSERS.includes(browser) || String(browser).includes('gecko') || String(browser).includes('firefox');
|
|
50
|
+
}
|
|
51
|
+
function isWebkitBasedBrowser(browser) {
|
|
52
|
+
return WEBKIT_BASED_BROWSERS.includes(browser) || String(browser).includes('webkit');
|
|
53
|
+
}
|
|
4
54
|
function stripBom(text) {
|
|
5
55
|
const raw = 'string' == typeof text ? text : String(text || '');
|
|
6
56
|
return raw && 0xfeff === raw.charCodeAt(0) ? raw.slice(1) : raw;
|
|
@@ -208,4 +258,4 @@ function validateDenoConfig(denoConfigPath) {
|
|
|
208
258
|
return false;
|
|
209
259
|
}
|
|
210
260
|
}
|
|
211
|
-
export { PROJECT_MANIFEST_FILENAMES, findNearestDenoConfigSync, findNearestProjectManifestDirSync, findNearestProjectManifestSync, hasProjectDependency, parseJsonSafe, readProjectDependencies, stripBom, validateDenoConfig };
|
|
261
|
+
export { CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, PROJECT_MANIFEST_FILENAMES, findNearestDenoConfigSync, findNearestProjectManifestDirSync, findNearestProjectManifestSync, hasProjectDependency, isChromiumBasedBrowser, isEmulatorBrowser, isEmulatorLaneEnabled, isGeckoBasedBrowser, isWebkitBasedBrowser, parseJsonSafe, readProjectDependencies, stripBom, validateDenoConfig };
|
package/dist/672~0.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
2
|
import pintor from "pintor";
|
|
3
|
-
import { isChromiumBasedBrowser, isGeckoBasedBrowser } from "./
|
|
4
|
-
import { parseJsonSafe } from "./731~0.mjs";
|
|
3
|
+
import { isChromiumBasedBrowser, parseJsonSafe, isGeckoBasedBrowser } from "./474~0.mjs";
|
|
5
4
|
import { prefix as messaging_prefix } from "./852~0.mjs";
|
|
6
5
|
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
7
6
|
const CHROMIUM_VENDOR_PREFIXES = [
|
package/dist/832~0.mjs
CHANGED
|
@@ -9,9 +9,8 @@ import node_path from "node:path";
|
|
|
9
9
|
import { getSpecialFoldersData } from "browser-extension-manifest-fields";
|
|
10
10
|
import pintor from "pintor";
|
|
11
11
|
import { devtoolsEngineFor, managedDependencyConflict, resolveProjectStructureSync, getDirs, computePreviewOutputPath, eventsPath as session_paths_eventsPath, anotherDevSessionActive, previewingSourceFallback, asAbsolute, displayPath, previewing, starting, debugPreviewOutput, ensureSessionArtifactsIgnoreFile, debugDirs, debugBrowser, readyContractPath, configLoadingError, normalizeBrowser, collapseHomeDir, previewingCustomOutput, browserArtifactsDir, getProjectStructure, isUsingExperimentalConfig as messages_isUsingExperimentalConfig, getDistPath, configBrowserOrThrow } from "./950~0.mjs";
|
|
12
|
-
import { isChromiumBasedBrowser,
|
|
12
|
+
import { isChromiumBasedBrowser, isEmulatorBrowser, isGeckoBasedBrowser, readProjectDependencies, stripBom, parseJsonSafe, isWebkitBasedBrowser } from "./474~0.mjs";
|
|
13
13
|
import { humanWarn, isDebug, browserRowValue, artifactNoun, prefix as messaging_prefix, card, humanLine } from "./852~0.mjs";
|
|
14
|
-
import { stripBom, parseJsonSafe, readProjectDependencies } from "./731~0.mjs";
|
|
15
14
|
import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
|
|
16
15
|
import { dirname as __rspack_dirname } from "node:path";
|
|
17
16
|
var __rspack_import_meta_dirname__ = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
|
|
@@ -19,7 +18,7 @@ import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
|
19
18
|
import * as __rspack_external_node_os_4f3c9d58 from "node:os";
|
|
20
19
|
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
21
20
|
import * as __rspack_external_node_vm_ef240610 from "node:vm";
|
|
22
|
-
var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.1.
|
|
21
|
+
var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.1.26","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"2.2.3","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","browser-extension-manifest-fields":"^3.0.1","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","cross-spawn":"^7.0.6","dotenv":"^17.2.3","es-module-lexer":"^3.0.2","extension-from-store":"^0.2.5","fflate":"^0.8.3","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.9.1","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.23","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
|
|
23
22
|
const preloadedEnvKeys = new Set();
|
|
24
23
|
function getPreloadedEnvKeys() {
|
|
25
24
|
return preloadedEnvKeys;
|
|
@@ -526,7 +525,7 @@ function getSessionRunId(packageJsonDir, browser) {
|
|
|
526
525
|
}
|
|
527
526
|
function deriveDistExtensionId(browser, distPath) {
|
|
528
527
|
try {
|
|
529
|
-
if (isWebkitBasedBrowser(browser)) return;
|
|
528
|
+
if (isWebkitBasedBrowser(browser) || isEmulatorBrowser(browser)) return;
|
|
530
529
|
if (!__rspack_external_node_fs_1b05aee1.existsSync(__rspack_external_node_path_806ed179.join(distPath, 'manifest.json'))) return;
|
|
531
530
|
const id = isGeckoBasedBrowser(browser) ? geckoExtensionId(distPath) : chromiumExtensionId(distPath);
|
|
532
531
|
return id || void 0;
|
|
@@ -630,7 +629,7 @@ function createPlaywrightMetadataWriter(options) {
|
|
|
630
629
|
instanceId: options.instanceId,
|
|
631
630
|
instanceExplicit: options.instanceExplicit
|
|
632
631
|
})) humanWarn(anotherDevSessionActive(options.browser, liveOwner.pid, liveOwner.runId));
|
|
633
|
-
const toManagedRecords = (dirs)=>Array.isArray(dirs) && dirs.length > 0 ? managedExtensionRecords(options.browser, dirs) : void 0;
|
|
632
|
+
const toManagedRecords = (dirs)=>Array.isArray(dirs) && dirs.length > 0 && !isEmulatorBrowser(options.browser) ? managedExtensionRecords(options.browser, dirs) : void 0;
|
|
634
633
|
let managedExtensionsExplicit = void 0 !== options.managedExtensionDirs;
|
|
635
634
|
let managedExtensions = toManagedRecords(options.managedExtensionDirs);
|
|
636
635
|
const base = {
|
|
@@ -652,7 +651,11 @@ function createPlaywrightMetadataWriter(options) {
|
|
|
652
651
|
controlPath: options.controlPath,
|
|
653
652
|
logsPath: options.logsPath,
|
|
654
653
|
toolchainVersion: package_namespaceObject.rE,
|
|
655
|
-
...readManifestProvenance(options.manifestPath)
|
|
654
|
+
...readManifestProvenance(options.manifestPath),
|
|
655
|
+
...isEmulatorBrowser(options.browser) ? {
|
|
656
|
+
engine: 'emulator',
|
|
657
|
+
browserPid: null
|
|
658
|
+
} : {}
|
|
656
659
|
};
|
|
657
660
|
function writeReady(status, extra) {
|
|
658
661
|
if (foreignLiveDevSession) return;
|
|
@@ -1512,6 +1515,7 @@ function readJsonRecord(filePath) {
|
|
|
1512
1515
|
}
|
|
1513
1516
|
}
|
|
1514
1517
|
function capitalizeToken(value) {
|
|
1518
|
+
if ('chromium-emulator' === value) return 'Emulated Chromium';
|
|
1515
1519
|
return value.split('-').filter(Boolean).map((token)=>token.charAt(0).toUpperCase() + token.slice(1)).join('-');
|
|
1516
1520
|
}
|
|
1517
1521
|
function getExtensionVersion() {
|
|
@@ -1563,6 +1567,9 @@ function shouldWarnPortConflict(requested, actual) {
|
|
|
1563
1567
|
const requestedPort = Number(requested);
|
|
1564
1568
|
return Number.isFinite(requestedPort) && 0 !== requestedPort && requestedPort !== actual;
|
|
1565
1569
|
}
|
|
1570
|
+
function emulatorViewerUrl(url) {
|
|
1571
|
+
return `${getLoggingPrefix('info')} Emulated Chromium runs in a web page. Open this address to load your extension:\n${pintor.underline(url)}`;
|
|
1572
|
+
}
|
|
1566
1573
|
function portInUse(requestedPort, newPort) {
|
|
1567
1574
|
return `${getLoggingPrefix('warn')} Port ${requestedPort} is in use.\nThe dev server listens on port ${newPort} instead.`;
|
|
1568
1575
|
}
|
|
@@ -1878,4 +1885,4 @@ async function extensionPreview(pathOrRemoteUrl, previewOptions, browserLauncher
|
|
|
1878
1885
|
metadata.writeShutdown(`the ${metadataCommand} session ended`);
|
|
1879
1886
|
});
|
|
1880
1887
|
}
|
|
1881
|
-
export { BUILD_COMMAND_DEFAULTS, DEV_COMMAND_DEFAULTS, PlaywrightPlugin, START_BUILD_DEFAULTS, assertNoManagedDependencyConflicts, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserRunnerDisabled, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, devServerRestarting, devServerStartTimeout, extensionJsRunnerError, extensionPreview, getPreloadedEnvKeys, getSessionRunId, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, loadBrowserConfig, loadCommandConfig, loadCustomConfig, loadProjectConfigDefaults, mergeOptionLayers, messages_ready, noEntrypointsDetected, package_namespaceObject, portInUse, publicFolderShadowed, publicMustBeAtProjectRoot, resolveCompanionExtensionDirs, resolveCompanionExtensionsConfig, runnerCleanupError, runnerUncaughtException, runnerUnhandledRejection, sanitize, serverRestartRequiredFromSpecialFolderMessageOnly, shouldWarnPortConflict, spacerLine, specialFolderChangeDetected, specialFoldersSetupSummary, stampReadyDistExtensionId, stampReadyKnownExtensionId, withDarkMode };
|
|
1888
|
+
export { BUILD_COMMAND_DEFAULTS, DEV_COMMAND_DEFAULTS, PlaywrightPlugin, START_BUILD_DEFAULTS, assertNoManagedDependencyConflicts, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserRunnerDisabled, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, devServerRestarting, devServerStartTimeout, emulatorViewerUrl, extensionJsRunnerError, extensionPreview, getPreloadedEnvKeys, getSessionRunId, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, loadBrowserConfig, loadCommandConfig, loadCustomConfig, loadProjectConfigDefaults, mergeOptionLayers, messages_ready, noEntrypointsDetected, package_namespaceObject, portInUse, publicFolderShadowed, publicMustBeAtProjectRoot, resolveCompanionExtensionDirs, resolveCompanionExtensionsConfig, runnerCleanupError, runnerUncaughtException, runnerUnhandledRejection, sanitize, serverRestartRequiredFromSpecialFolderMessageOnly, shouldWarnPortConflict, spacerLine, specialFolderChangeDetected, specialFoldersSetupSummary, stampReadyDistExtensionId, stampReadyKnownExtensionId, withDarkMode };
|
package/dist/840~0.mjs
CHANGED
|
@@ -9,8 +9,7 @@ import { pathToFileURL } from "node:url";
|
|
|
9
9
|
import { EventEmitter } from "node:events";
|
|
10
10
|
import { humanWarn, browserRowValue, CODES, ENVELOPE, prefix as messaging_prefix, card, isDebug, claimCardKey, isMachineOutput } from "./852~0.mjs";
|
|
11
11
|
import { package_namespaceObject, loadCommandConfig, DEV_COMMAND_DEFAULTS, stampReadyDistExtensionId, loadProjectConfigDefaults, mergeOptionLayers, stampReadyKnownExtensionId, assertNoManagedDependencyConflicts, loadCustomConfig, START_BUILD_DEFAULTS, loadBrowserConfig, resolveCompanionExtensionsConfig, BUILD_COMMAND_DEFAULTS, getSpecialFoldersDataForProjectRoot, withDarkMode } from "./832~0.mjs";
|
|
12
|
-
import { stripBom, hasProjectDependency, parseJsonSafe, findNearestProjectManifestDirSync } from "./
|
|
13
|
-
import { isGeckoBasedBrowser } from "./331~0.mjs";
|
|
12
|
+
import { stripBom, hasProjectDependency, isGeckoBasedBrowser, parseJsonSafe, findNearestProjectManifestDirSync } from "./474~0.mjs";
|
|
14
13
|
import { buildWarningsDetails, buildFailed, getDirs, zipArtifactReady, projectInstallFallbackToNpm, debugDirs, addonLintDependencyAttribution, browserLaunchFailed, collapseHomeDir, addonLintMore, extensionLoadStillRefused, extensionLoadRecovered, writingTypeDefinitionsError, operaBuildUnminified, projectInstallScriptsDisabled, authorInstallNotice, addonLintFailed, buildAssetsTree, addonLintSummary, addonLintFinding, relativeToDir, configBrowserOrThrow, needsInstall, projectInstallInWorkspaceRoot, buildCommandFailed, addonLintNotInstalled, writingTypeDefinitions, buildComplete, buildSummaryPath, displayPath, ensureSessionStateInProjectGitignore, ensureSessionArtifactsIgnoreFile, debugBrowser, normalizeBrowser, debugOutputPath, devCommandFailed, buildShareHint, getDistPath, getProjectStructure, debugSplitChunksNarrowed } from "./950~0.mjs";
|
|
15
14
|
import { publicRootsFor } from "./105~0.mjs";
|
|
16
15
|
import { getCanonicalContentScriptEntryName } from "./640~0.mjs";
|
|
@@ -2995,6 +2994,7 @@ class BrowsersPlugin {
|
|
|
2995
2994
|
controller;
|
|
2996
2995
|
reloadBroker;
|
|
2997
2996
|
logSink;
|
|
2997
|
+
emulatorViewerUrl;
|
|
2998
2998
|
lastReportedRefusal;
|
|
2999
2999
|
constructor(options){
|
|
3000
3000
|
this.options = options;
|
|
@@ -3005,6 +3005,9 @@ class BrowsersPlugin {
|
|
|
3005
3005
|
setLogSink(sink) {
|
|
3006
3006
|
this.logSink = sink;
|
|
3007
3007
|
}
|
|
3008
|
+
setEmulatorViewerUrl(url) {
|
|
3009
|
+
this.emulatorViewerUrl = url;
|
|
3010
|
+
}
|
|
3008
3011
|
async retryRefusedExtensionLoad() {
|
|
3009
3012
|
const controller = this.controller;
|
|
3010
3013
|
if (!controller?.retryExtensionLoad || !controller.getExtensionLoadRefusal) return false;
|
|
@@ -3055,7 +3058,10 @@ class BrowsersPlugin {
|
|
|
3055
3058
|
outputPath,
|
|
3056
3059
|
contextDir,
|
|
3057
3060
|
extensionsToLoad: this.extensionsToLoad,
|
|
3058
|
-
logSink: this.logSink
|
|
3061
|
+
logSink: this.logSink,
|
|
3062
|
+
...this.emulatorViewerUrl ? {
|
|
3063
|
+
emulatorViewerUrl: this.emulatorViewerUrl
|
|
3064
|
+
} : {}
|
|
3059
3065
|
});
|
|
3060
3066
|
const logLevel = this.options.browserOptions.logLevel || 'off';
|
|
3061
3067
|
if ('off' !== logLevel && this.controller) await this.controller.enableUnifiedLogging({
|
package/dist/950~0.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { createRequire as __extjsCreateRequire } from "node:module"; const requi
|
|
|
2
2
|
import pintor from "pintor";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { fmt, isDebug, artifactNoun, prefix as messaging_prefix, hasChannelPrefix } from "./852~0.mjs";
|
|
5
|
-
import { findNearestDenoConfigSync, validateDenoConfig, PROJECT_MANIFEST_FILENAMES, parseJsonSafe, readProjectDependencies } from "./
|
|
5
|
+
import { findNearestDenoConfigSync, isEmulatorLaneEnabled, validateDenoConfig, isEmulatorBrowser, PROJECT_MANIFEST_FILENAMES, parseJsonSafe, readProjectDependencies } from "./474~0.mjs";
|
|
6
6
|
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
7
7
|
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
8
8
|
import * as __rspack_external_node_os_4f3c9d58 from "node:os";
|
|
@@ -821,7 +821,9 @@ const KNOWN_BROWSER_NAMES = new Set([
|
|
|
821
821
|
'webkit-based'
|
|
822
822
|
]);
|
|
823
823
|
function isKnownBrowserName(name) {
|
|
824
|
-
|
|
824
|
+
if ('string' != typeof name) return false;
|
|
825
|
+
if (isEmulatorBrowser(name)) return isEmulatorLaneEnabled();
|
|
826
|
+
return KNOWN_BROWSER_NAMES.has(name);
|
|
825
827
|
}
|
|
826
828
|
function configBrowserOrThrow(configBrowser, command) {
|
|
827
829
|
if (null == configBrowser) return;
|
|
@@ -878,6 +880,9 @@ function normalizeBrowser(browser, chromiumBinary, geckoBinary, safariBinary) {
|
|
|
878
880
|
return 'safari';
|
|
879
881
|
case 'webkit-based':
|
|
880
882
|
return 'webkit-based';
|
|
883
|
+
case 'chromium-emulator':
|
|
884
|
+
if (isEmulatorLaneEnabled()) return 'chromium-emulator';
|
|
885
|
+
return 'chrome';
|
|
881
886
|
default:
|
|
882
887
|
return 'chrome';
|
|
883
888
|
}
|
|
@@ -904,6 +909,7 @@ function devtoolsEngineFor(browser) {
|
|
|
904
909
|
return 'edge';
|
|
905
910
|
case 'chromium':
|
|
906
911
|
case 'chromium-based':
|
|
912
|
+
case 'chromium-emulator':
|
|
907
913
|
case 'brave':
|
|
908
914
|
case 'opera':
|
|
909
915
|
case 'vivaldi':
|
package/dist/bridge.mjs
CHANGED
|
@@ -27,6 +27,7 @@ function readReadyContract(projectPath, browser = 'chrome') {
|
|
|
27
27
|
schema: 'number' == typeof c.schema ? c.schema : void 0,
|
|
28
28
|
logsPath: c.logsPath,
|
|
29
29
|
status: c.status,
|
|
30
|
+
engine: 'string' == typeof c.engine ? c.engine : void 0,
|
|
30
31
|
pid: 'number' == typeof c.pid ? c.pid : void 0,
|
|
31
32
|
cdpPort: 'number' == typeof c.cdpPort ? c.cdpPort : void 0,
|
|
32
33
|
browserExitedAt: 'string' == typeof c.browserExitedAt ? c.browserExitedAt : void 0,
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { type ActionsSink } from './actions-file.js';
|
|
2
|
-
import { type AnyFrame, type CommandFrame, type DevReloadKind, type IncomingLogEvent, type ServerFrame } from './contracts.js';
|
|
2
|
+
import { type AnyFrame, type BridgeEngine, type CommandFrame, type DevReloadKind, type IncomingLogEvent, type ServerFrame } from './contracts.js';
|
|
3
3
|
import type { LogsFileWriter } from './logs-file.js';
|
|
4
4
|
import { LogRingBuffer } from './ring-buffer.js';
|
|
5
5
|
export interface BridgeConnection {
|
|
6
6
|
readonly id: string;
|
|
7
|
+
readonly origin?: string;
|
|
7
8
|
send(frame: ServerFrame | CommandFrame): void;
|
|
8
9
|
close(code?: number, reason?: string): void;
|
|
9
10
|
}
|
|
10
11
|
export interface BridgeBrokerOptions {
|
|
11
12
|
instanceId: string;
|
|
12
13
|
runId: string;
|
|
13
|
-
engine?:
|
|
14
|
+
engine?: BridgeEngine;
|
|
15
|
+
viewerOrigin?: string | null;
|
|
14
16
|
ring?: LogRingBuffer;
|
|
15
17
|
file?: LogsFileWriter;
|
|
16
18
|
allowControl?: boolean;
|
|
@@ -31,6 +33,8 @@ export declare class BridgeBroker {
|
|
|
31
33
|
private readonly instanceId;
|
|
32
34
|
private readonly runId;
|
|
33
35
|
private readonly engine?;
|
|
36
|
+
private readonly viewerOrigin;
|
|
37
|
+
private viewerEverConnected;
|
|
34
38
|
private readonly ring;
|
|
35
39
|
private readonly file?;
|
|
36
40
|
private readonly roles;
|
|
@@ -57,6 +61,7 @@ export declare class BridgeBroker {
|
|
|
57
61
|
get consumerCount(): number;
|
|
58
62
|
get producerCount(): number;
|
|
59
63
|
get controllerCount(): number;
|
|
64
|
+
get viewerCount(): number;
|
|
60
65
|
get pendingCount(): number;
|
|
61
66
|
onFrame(conn: BridgeConnection, frame: AnyFrame): void;
|
|
62
67
|
onClose(conn: BridgeConnection): void;
|
|
@@ -83,5 +88,6 @@ export declare class BridgeBroker {
|
|
|
83
88
|
private firstExecutor;
|
|
84
89
|
private audit;
|
|
85
90
|
private fanOut;
|
|
91
|
+
private isReloadReceiver;
|
|
86
92
|
private countRole;
|
|
87
93
|
}
|
|
@@ -10,6 +10,7 @@ export interface ReadyContractInfo {
|
|
|
10
10
|
schema?: number;
|
|
11
11
|
logsPath?: string;
|
|
12
12
|
status?: string;
|
|
13
|
+
engine?: string;
|
|
13
14
|
/** Dev-server pid; absent in pre-4.1 contracts. */
|
|
14
15
|
pid?: number;
|
|
15
16
|
/** Browser CDP port, stamped post-launch, may lag `status: 'ready'`. */
|
|
@@ -33,7 +33,8 @@ export interface LogEvent {
|
|
|
33
33
|
export type IncomingLogEvent = Omit<LogEvent, 'seq'> & {
|
|
34
34
|
seq?: number;
|
|
35
35
|
};
|
|
36
|
-
export type BridgeRole = 'producer' | 'consumer' | 'controller';
|
|
36
|
+
export type BridgeRole = 'producer' | 'consumer' | 'controller' | 'viewer';
|
|
37
|
+
export type BridgeEngine = 'chromium' | 'firefox' | 'webkit' | 'emulator';
|
|
37
38
|
export interface BridgeTarget {
|
|
38
39
|
context: 'background' | 'popup' | 'options' | 'sidebar' | 'devtools' | 'content' | 'page';
|
|
39
40
|
url?: string;
|
|
@@ -68,7 +69,7 @@ export interface ReadyFrame {
|
|
|
68
69
|
type: 'ready';
|
|
69
70
|
runId: string;
|
|
70
71
|
bufferedFrom?: number;
|
|
71
|
-
engine?:
|
|
72
|
+
engine?: BridgeEngine;
|
|
72
73
|
capabilities?: {
|
|
73
74
|
eval?: boolean;
|
|
74
75
|
storage?: boolean;
|
|
@@ -9,6 +9,8 @@ export interface StartControlServerOptions {
|
|
|
9
9
|
host?: string;
|
|
10
10
|
port?: number;
|
|
11
11
|
path?: string;
|
|
12
|
+
viewerOrigin?: string | null;
|
|
12
13
|
}
|
|
13
14
|
export declare function isWebOrigin(origin: string | undefined): boolean;
|
|
15
|
+
export declare function isAdmittedOrigin(origin: string | undefined, viewerOrigin?: string | null): boolean;
|
|
14
16
|
export declare function startControlServer(options: StartControlServerOptions): Promise<ControlServer>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ReadStream } from 'node:fs';
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
+
export interface OutputFileSystemLike {
|
|
4
|
+
readFileSync?: (filePath: string) => Buffer;
|
|
5
|
+
}
|
|
6
|
+
export interface ActiveCompilerRef {
|
|
7
|
+
outputPath(): string | undefined;
|
|
8
|
+
outputFileSystem(): OutputFileSystemLike | undefined;
|
|
9
|
+
}
|
|
10
|
+
type ResponseData = Buffer | ReadStream;
|
|
11
|
+
interface ModifiedResponseData {
|
|
12
|
+
data: ResponseData;
|
|
13
|
+
byteLength: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function createResponseDataRepair(ref: ActiveCompilerRef): (req: IncomingMessage, res: ServerResponse, data: ResponseData, byteLength: number) => ModifiedResponseData;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
export declare const EMULATOR_FILES_PATH = "/__extjs-emulator/files.json";
|
|
3
|
+
export declare const EMULATOR_FILES_VERSION: 1;
|
|
4
|
+
export declare const EMULATOR_WIRE_VERSION = "1";
|
|
5
|
+
export declare const DEFAULT_EMULATOR_ORIGIN = "https://browsers.extension.land";
|
|
6
|
+
export interface EmulatorFileEntry {
|
|
7
|
+
path: string;
|
|
8
|
+
size: number;
|
|
9
|
+
sha256: string;
|
|
10
|
+
}
|
|
11
|
+
export interface EmulatorFileIndex {
|
|
12
|
+
version: typeof EMULATOR_FILES_VERSION;
|
|
13
|
+
instanceId: string;
|
|
14
|
+
root: '/';
|
|
15
|
+
livereload?: {
|
|
16
|
+
path: string;
|
|
17
|
+
};
|
|
18
|
+
files: EmulatorFileEntry[];
|
|
19
|
+
}
|
|
20
|
+
export declare function normalizeWebOrigin(value: unknown): string | null;
|
|
21
|
+
export declare function resolveEmulatorOrigin(env?: NodeJS.ProcessEnv): string;
|
|
22
|
+
export declare function isSameWebOrigin(candidate: unknown, expected: string | null | undefined): boolean;
|
|
23
|
+
export declare function buildEmulatorViewerUrl(options: {
|
|
24
|
+
origin: string;
|
|
25
|
+
host: string;
|
|
26
|
+
port: number;
|
|
27
|
+
controlPort: number | null;
|
|
28
|
+
controlPath: string;
|
|
29
|
+
instanceId: string;
|
|
30
|
+
}): string;
|
|
31
|
+
export interface EmulatorAssetLike {
|
|
32
|
+
name: string;
|
|
33
|
+
source: {
|
|
34
|
+
buffer(): Buffer;
|
|
35
|
+
};
|
|
36
|
+
info?: {
|
|
37
|
+
hotModuleReplacement?: boolean;
|
|
38
|
+
related?: Record<string, string | string[] | undefined>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export declare function buildEmulatorFileIndex(assets: Iterable<EmulatorAssetLike>, instanceId: string): EmulatorFileIndex;
|
|
42
|
+
export declare function resolveLivereloadPath(webSocketServer: unknown): string | null;
|
|
43
|
+
export interface EmulatorFileIndexHolder {
|
|
44
|
+
publish(assets: Iterable<EmulatorAssetLike>): EmulatorFileIndex;
|
|
45
|
+
reset(): void;
|
|
46
|
+
setLivereloadPath(socketPath: string | null): void;
|
|
47
|
+
current(): Promise<EmulatorFileIndex>;
|
|
48
|
+
}
|
|
49
|
+
export declare function createEmulatorFileIndexHolder(instanceId: string): EmulatorFileIndexHolder;
|
|
50
|
+
export declare function attachEmulatorFileIndex(compiler: unknown, holder: EmulatorFileIndexHolder): void;
|
|
51
|
+
export declare function createEmulatorFilesMiddlewareEntry(holder: EmulatorFileIndexHolder, devServer: unknown): {
|
|
52
|
+
name: string;
|
|
53
|
+
path: string;
|
|
54
|
+
middleware: (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => Promise<void>;
|
|
55
|
+
};
|
|
56
|
+
export declare function createEmulatorFilesMiddleware(holder: EmulatorFileIndexHolder): (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => Promise<void>;
|
|
@@ -6,6 +6,7 @@ export declare function browserRunnerDisabled(args: {
|
|
|
6
6
|
distPath?: string;
|
|
7
7
|
}): string;
|
|
8
8
|
export declare function shouldWarnPortConflict(requested: unknown, actual: number): boolean;
|
|
9
|
+
export declare function emulatorViewerUrl(url: string): string;
|
|
9
10
|
export declare function portInUse(requestedPort: number, newPort: number): string;
|
|
10
11
|
export declare function extensionJsRunnerError(error: unknown): string;
|
|
11
12
|
export declare function autoExitModeEnabled(ms: number): string;
|
package/dist/dev-server~0.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
3
3
|
import node_fs from "node:fs";
|
|
4
4
|
import { Writable } from "node:stream";
|
|
5
5
|
import { rspack } from "@rspack/core";
|
|
@@ -7,14 +7,13 @@ import { RspackDevServer } from "@rspack/dev-server";
|
|
|
7
7
|
import { merge } from "webpack-merge";
|
|
8
8
|
import { WebSocket, WebSocketServer } from "ws";
|
|
9
9
|
import { classifyReloadFromSources, attachLifecycleStream, readContentScriptCount, humanLine, createChangedSourcesTracker, buildSourceFeatureIndex, applySplitChunksGuard, createLifecycleStream, dispatchReload } from "./840~0.mjs";
|
|
10
|
-
import { runnerCleanupError, autoExitForceKill, loadCommandConfig, sanitize, extensionJsRunnerError, portInUse, devServerStartTimeout, autoExitTriggered, loadProjectConfigDefaults, runnerUncaughtException, shouldWarnPortConflict, devServerRestarting, DEV_COMMAND_DEFAULTS, mergeOptionLayers, runnerUnhandledRejection, createPlaywrightMetadataWriter, autoExitModeEnabled, getSessionRunId, loadCustomConfig, loadBrowserConfig, resolveCompanionExtensionsConfig, getSpecialFoldersDataForProjectRoot } from "./832~0.mjs";
|
|
10
|
+
import { runnerCleanupError, autoExitForceKill, loadCommandConfig, sanitize, extensionJsRunnerError, portInUse, devServerStartTimeout, autoExitTriggered, loadProjectConfigDefaults, runnerUncaughtException, shouldWarnPortConflict, devServerRestarting, DEV_COMMAND_DEFAULTS, mergeOptionLayers, runnerUnhandledRejection, createPlaywrightMetadataWriter, autoExitModeEnabled, emulatorViewerUrl, getSessionRunId, loadCustomConfig, loadBrowserConfig, resolveCompanionExtensionsConfig, getSpecialFoldersDataForProjectRoot } from "./832~0.mjs";
|
|
11
11
|
import { CONTROL_WS_PATH, writePersistedControlPort, writeControlToken, clearControlToken, readPersistedControlPort } from "./616~0.mjs";
|
|
12
|
-
import { hasProjectDependency, findNearestProjectManifestDirSync } from "./
|
|
12
|
+
import { isGeckoBasedBrowser, hasProjectDependency, isEmulatorBrowser, findNearestProjectManifestDirSync, isWebkitBasedBrowser } from "./474~0.mjs";
|
|
13
13
|
import { publicFolderOrDefault } from "./105~0.mjs";
|
|
14
14
|
import { setupNoBrowserBannerOnFirstDone, DevSessionRestartScheduler, resolveConnectableHost, default as webpackConfig, bindDevSessionRestart, unbindDevSessionRestart, setupCompilerLifecycleHooks } from "./rspack-config~0.mjs";
|
|
15
15
|
import { logsPath, controlPortFilePath, legacyControlPortFilePath, asAbsolute, getDistPath, ensureSessionStateInProjectGitignore, actionsPath, ensureSessionArtifactsIgnoreFile } from "./950~0.mjs";
|
|
16
16
|
import { isDebug } from "./852~0.mjs";
|
|
17
|
-
import { isGeckoBasedBrowser, isWebkitBasedBrowser } from "./331~0.mjs";
|
|
18
17
|
import * as __rspack_external_node_os_4f3c9d58 from "node:os";
|
|
19
18
|
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
20
19
|
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
@@ -181,6 +180,173 @@ function fnv1aHex(input) {
|
|
|
181
180
|
}
|
|
182
181
|
return (hash >>> 0).toString(16).padStart(8, '0');
|
|
183
182
|
}
|
|
183
|
+
const EMULATOR_FILES_PATH = '/__extjs-emulator/files.json';
|
|
184
|
+
const EMULATOR_FILES_VERSION = 1;
|
|
185
|
+
const EMULATOR_WIRE_VERSION = '1';
|
|
186
|
+
const DEFAULT_EMULATOR_ORIGIN = 'https://browsers.extension.land';
|
|
187
|
+
function normalizeWebOrigin(value) {
|
|
188
|
+
const raw = String(value ?? '').trim();
|
|
189
|
+
if (!raw) return null;
|
|
190
|
+
let url;
|
|
191
|
+
try {
|
|
192
|
+
url = new URL(raw);
|
|
193
|
+
} catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
if ('http:' !== url.protocol && 'https:' !== url.protocol) return null;
|
|
197
|
+
if (url.username || url.password) return null;
|
|
198
|
+
return url.origin;
|
|
199
|
+
}
|
|
200
|
+
function resolveEmulatorOrigin(env = process.env) {
|
|
201
|
+
const configured = String(env.EXTENSION_EMULATOR_ORIGIN || '').trim();
|
|
202
|
+
if (!configured) return DEFAULT_EMULATOR_ORIGIN;
|
|
203
|
+
const origin = normalizeWebOrigin(configured);
|
|
204
|
+
if (!origin) throw new Error(`EXTENSION_EMULATOR_ORIGIN must be an http or https origin, got: ${configured}`);
|
|
205
|
+
return origin;
|
|
206
|
+
}
|
|
207
|
+
function isSameWebOrigin(candidate, expected) {
|
|
208
|
+
if (!expected) return false;
|
|
209
|
+
const left = normalizeWebOrigin(candidate);
|
|
210
|
+
const right = normalizeWebOrigin(expected);
|
|
211
|
+
return null !== left && left === right;
|
|
212
|
+
}
|
|
213
|
+
function buildEmulatorViewerUrl(options) {
|
|
214
|
+
const host = options.host.includes(':') ? `[${options.host}]` : options.host;
|
|
215
|
+
const params = new URLSearchParams();
|
|
216
|
+
params.set('files', `http://${host}:${options.port}${EMULATOR_FILES_PATH}`);
|
|
217
|
+
if (null != options.controlPort) params.set('control', `ws://${host}:${options.controlPort}${options.controlPath}`);
|
|
218
|
+
params.set('instance', options.instanceId);
|
|
219
|
+
params.set('v', EMULATOR_WIRE_VERSION);
|
|
220
|
+
return `${options.origin}/chromium/#${params.toString()}`;
|
|
221
|
+
}
|
|
222
|
+
function hotModuleReplacementNames(assets) {
|
|
223
|
+
const names = new Set();
|
|
224
|
+
for (const asset of assets)if (asset.info?.hotModuleReplacement) {
|
|
225
|
+
names.add(asset.name);
|
|
226
|
+
for (const related of Object.values(asset.info.related || {}))for (const name of [].concat(related))if (name) names.add(name);
|
|
227
|
+
}
|
|
228
|
+
return names;
|
|
229
|
+
}
|
|
230
|
+
function isServableAssetName(name) {
|
|
231
|
+
if (!name || name.startsWith('/') || name.includes('\\')) return false;
|
|
232
|
+
return !/(?:^|\/)\.\.(?:\/|$)/.test(name);
|
|
233
|
+
}
|
|
234
|
+
function servedAssetPath(name) {
|
|
235
|
+
return name.split('/').filter((segment, index)=>'' !== segment && !('.' === segment && index > 0)).join('/');
|
|
236
|
+
}
|
|
237
|
+
function buildEmulatorFileIndex(assets, instanceId) {
|
|
238
|
+
const list = Array.from(assets);
|
|
239
|
+
const hotNames = hotModuleReplacementNames(list);
|
|
240
|
+
const files = [];
|
|
241
|
+
const listed = new Set();
|
|
242
|
+
for (const asset of list){
|
|
243
|
+
const name = String(asset.name || '');
|
|
244
|
+
if (!isServableAssetName(name) || hotNames.has(name)) continue;
|
|
245
|
+
const servedPath = servedAssetPath(name);
|
|
246
|
+
if (!servedPath || listed.has(servedPath)) continue;
|
|
247
|
+
listed.add(servedPath);
|
|
248
|
+
const bytes = asset.source.buffer();
|
|
249
|
+
files.push({
|
|
250
|
+
path: servedPath,
|
|
251
|
+
size: bytes.length,
|
|
252
|
+
sha256: createHash('sha256').update(bytes).digest('hex')
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
files.sort((a, b)=>a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
256
|
+
return {
|
|
257
|
+
version: EMULATOR_FILES_VERSION,
|
|
258
|
+
instanceId,
|
|
259
|
+
root: '/',
|
|
260
|
+
files
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function resolveLivereloadPath(webSocketServer) {
|
|
264
|
+
if (!webSocketServer || 'object' != typeof webSocketServer) return null;
|
|
265
|
+
const options = webSocketServer.options;
|
|
266
|
+
const socketPath = options?.path;
|
|
267
|
+
return 'string' == typeof socketPath && socketPath.startsWith('/') ? socketPath : null;
|
|
268
|
+
}
|
|
269
|
+
function createEmulatorFileIndexHolder(instanceId) {
|
|
270
|
+
let latest = null;
|
|
271
|
+
let livereloadPath = null;
|
|
272
|
+
let waiters = [];
|
|
273
|
+
const withLivereload = (index)=>livereloadPath ? {
|
|
274
|
+
version: index.version,
|
|
275
|
+
instanceId: index.instanceId,
|
|
276
|
+
root: index.root,
|
|
277
|
+
livereload: {
|
|
278
|
+
path: livereloadPath
|
|
279
|
+
},
|
|
280
|
+
files: index.files
|
|
281
|
+
} : index;
|
|
282
|
+
return {
|
|
283
|
+
publish (assets) {
|
|
284
|
+
latest = buildEmulatorFileIndex(assets, instanceId);
|
|
285
|
+
const ready = waiters;
|
|
286
|
+
waiters = [];
|
|
287
|
+
for (const resolve of ready)resolve(withLivereload(latest));
|
|
288
|
+
return withLivereload(latest);
|
|
289
|
+
},
|
|
290
|
+
reset () {
|
|
291
|
+
latest = null;
|
|
292
|
+
},
|
|
293
|
+
setLivereloadPath (socketPath) {
|
|
294
|
+
livereloadPath = socketPath;
|
|
295
|
+
},
|
|
296
|
+
current () {
|
|
297
|
+
if (latest) return Promise.resolve(withLivereload(latest));
|
|
298
|
+
return new Promise((resolve)=>{
|
|
299
|
+
waiters.push(resolve);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function attachEmulatorFileIndex(compiler, holder) {
|
|
305
|
+
const done = compiler?.hooks?.done;
|
|
306
|
+
if (!done) return;
|
|
307
|
+
holder.reset();
|
|
308
|
+
done.tap({
|
|
309
|
+
name: 'extjs-emulator-files',
|
|
310
|
+
stage: -100
|
|
311
|
+
}, (stats)=>{
|
|
312
|
+
if (stats.compilation.errors?.length) return;
|
|
313
|
+
holder.publish(stats.compilation.getAssets());
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function createEmulatorFilesMiddlewareEntry(holder, devServer) {
|
|
317
|
+
const options = devServer?.options;
|
|
318
|
+
holder.setLivereloadPath(resolveLivereloadPath(options?.webSocketServer));
|
|
319
|
+
return {
|
|
320
|
+
name: 'extjs-emulator-files',
|
|
321
|
+
path: EMULATOR_FILES_PATH,
|
|
322
|
+
middleware: createEmulatorFilesMiddleware(holder)
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function createEmulatorFilesMiddleware(holder) {
|
|
326
|
+
return async (req, res, next)=>{
|
|
327
|
+
const method = String(req.method || 'GET').toUpperCase();
|
|
328
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
329
|
+
res.setHeader('Access-Control-Allow-Private-Network', 'true');
|
|
330
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
331
|
+
if ('OPTIONS' === method) {
|
|
332
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
|
|
333
|
+
res.statusCode = 204;
|
|
334
|
+
res.end();
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if ('GET' !== method && 'HEAD' !== method) return void next();
|
|
338
|
+
try {
|
|
339
|
+
const index = await holder.current();
|
|
340
|
+
const body = JSON.stringify(index);
|
|
341
|
+
res.statusCode = 200;
|
|
342
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
343
|
+
res.setHeader('Content-Length', Buffer.byteLength(body));
|
|
344
|
+
res.end('HEAD' === method ? void 0 : body);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
next(error);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
184
350
|
const DEFAULT_RING_CAPACITY = 5000;
|
|
185
351
|
class LogRingBuffer {
|
|
186
352
|
capacity;
|
|
@@ -263,10 +429,16 @@ const UNDELIVERED_RELOAD_WARN = {
|
|
|
263
429
|
'recently-disconnected': "SW not attached, your edit compiled but no page received it. The extension's service worker disconnected (MV3 workers idle out, or the browser may have exited). Reloads resume automatically once it reconnects."
|
|
264
430
|
};
|
|
265
431
|
const UNDELIVERED_RELOAD_WARN_WEBKIT_NEVER_CONNECTED = "Extension not connected, your edit compiled but no page received it. The extension has not connected to the dev server this session. Open Safari > Settings > Extensions and turn it on. Safari restarts the extension itself once it is enabled, and reloads resume automatically.";
|
|
432
|
+
const UNDELIVERED_RELOAD_WARN_EMULATOR = {
|
|
433
|
+
'never-connected': "No emulated Chromium page is connected, your edit compiled but no page received it. Open the emulated Chromium URL the dev server printed; reloads resume automatically once the page connects.",
|
|
434
|
+
'recently-disconnected': "The emulated Chromium page disconnected, your edit compiled but no page received it. Reopen the emulated Chromium URL the dev server printed; reloads resume automatically once the page reconnects."
|
|
435
|
+
};
|
|
266
436
|
class BridgeBroker {
|
|
267
437
|
instanceId;
|
|
268
438
|
runId;
|
|
269
439
|
engine;
|
|
440
|
+
viewerOrigin;
|
|
441
|
+
viewerEverConnected = false;
|
|
270
442
|
ring;
|
|
271
443
|
file;
|
|
272
444
|
roles = new Map();
|
|
@@ -293,6 +465,7 @@ class BridgeBroker {
|
|
|
293
465
|
this.instanceId = options.instanceId;
|
|
294
466
|
this.runId = options.runId;
|
|
295
467
|
this.engine = options.engine;
|
|
468
|
+
this.viewerOrigin = normalizeWebOrigin(options.viewerOrigin);
|
|
296
469
|
this.ring = options.ring ?? new LogRingBuffer();
|
|
297
470
|
this.file = options.file;
|
|
298
471
|
this.allowEval = options.allowEval ?? false;
|
|
@@ -316,6 +489,9 @@ class BridgeBroker {
|
|
|
316
489
|
get controllerCount() {
|
|
317
490
|
return this.countRole('controller');
|
|
318
491
|
}
|
|
492
|
+
get viewerCount() {
|
|
493
|
+
return this.countRole('viewer');
|
|
494
|
+
}
|
|
319
495
|
get pendingCount() {
|
|
320
496
|
return this.pending.size;
|
|
321
497
|
}
|
|
@@ -334,7 +510,7 @@ class BridgeBroker {
|
|
|
334
510
|
if ('producer' === this.roles.get(conn)) this.onResult(frame);
|
|
335
511
|
return;
|
|
336
512
|
case 'reload-ack':
|
|
337
|
-
if (
|
|
513
|
+
if (this.isReloadReceiver(this.roles.get(conn)) && this.pendingReload?.reloadType === frame.reloadType) this.pendingReload = void 0;
|
|
338
514
|
return;
|
|
339
515
|
default:
|
|
340
516
|
return;
|
|
@@ -368,7 +544,7 @@ class BridgeBroker {
|
|
|
368
544
|
} : {}
|
|
369
545
|
};
|
|
370
546
|
let notified = 0;
|
|
371
|
-
for (const [conn, role] of this.roles)if (
|
|
547
|
+
for (const [conn, role] of this.roles)if (this.isReloadReceiver(role)) try {
|
|
372
548
|
conn.send(frame);
|
|
373
549
|
notified++;
|
|
374
550
|
} catch {}
|
|
@@ -379,11 +555,12 @@ class BridgeBroker {
|
|
|
379
555
|
const now = this.now();
|
|
380
556
|
if (now - this.sessionStartedAt < UNDELIVERED_RELOAD_GRACE_MS) return null;
|
|
381
557
|
if (null != this.lastStaleHelloAt && now - this.lastStaleHelloAt < STALE_RESYNC_HINT_MS) return null;
|
|
382
|
-
const kind = this.producerEverConnected ? 'recently-disconnected' : 'never-connected';
|
|
558
|
+
const kind = this.producerEverConnected || this.viewerEverConnected ? 'recently-disconnected' : 'never-connected';
|
|
383
559
|
if (options?.producerRestartExpected && 'recently-disconnected' === kind) return null;
|
|
384
560
|
if (this.lastUndeliveredWarnKind === kind) return null;
|
|
385
561
|
this.lastUndeliveredWarnKind = kind;
|
|
386
562
|
if ('never-connected' === kind && 'webkit' === this.engine) return UNDELIVERED_RELOAD_WARN_WEBKIT_NEVER_CONNECTED;
|
|
563
|
+
if ('emulator' === this.engine) return UNDELIVERED_RELOAD_WARN_EMULATOR[kind];
|
|
387
564
|
return UNDELIVERED_RELOAD_WARN[kind];
|
|
388
565
|
}
|
|
389
566
|
pingProducers() {
|
|
@@ -423,6 +600,26 @@ class BridgeBroker {
|
|
|
423
600
|
}
|
|
424
601
|
onHello(conn, hello) {
|
|
425
602
|
if (1 !== hello.v) return void conn.close(4002, 'unsupported envelope version');
|
|
603
|
+
const fromViewerOrigin = isSameWebOrigin(conn.origin, this.viewerOrigin);
|
|
604
|
+
if ('viewer' === hello.role && !fromViewerOrigin) return void conn.close(4002, 'viewer not allowed from this origin');
|
|
605
|
+
if (fromViewerOrigin && 'viewer' !== hello.role) return void conn.close(4002, 'only the viewer role is allowed from a web origin');
|
|
606
|
+
if ('viewer' === hello.role) {
|
|
607
|
+
if (hello.instanceId !== this.instanceId) return void conn.close(4001, 'instanceId mismatch');
|
|
608
|
+
this.roles.set(conn, 'viewer');
|
|
609
|
+
this.viewerEverConnected = true;
|
|
610
|
+
this.lastUndeliveredWarnKind = null;
|
|
611
|
+
conn.send({
|
|
612
|
+
type: 'ready',
|
|
613
|
+
runId: this.runId,
|
|
614
|
+
engine: this.engine
|
|
615
|
+
});
|
|
616
|
+
if (this.pendingReload) {
|
|
617
|
+
const frame = this.pendingReload;
|
|
618
|
+
this.pendingReload = void 0;
|
|
619
|
+
conn.send(frame);
|
|
620
|
+
}
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
426
623
|
if (hello.instanceId !== this.instanceId) {
|
|
427
624
|
if ('producer' === hello.role) {
|
|
428
625
|
this.lastStaleHelloAt = this.now();
|
|
@@ -632,6 +829,9 @@ class BridgeBroker {
|
|
|
632
829
|
conn.send(frame);
|
|
633
830
|
} catch {}
|
|
634
831
|
}
|
|
832
|
+
isReloadReceiver(role) {
|
|
833
|
+
return 'producer' === role || 'viewer' === role;
|
|
834
|
+
}
|
|
635
835
|
countRole(role) {
|
|
636
836
|
let n = 0;
|
|
637
837
|
for (const r of this.roles.values())if (r === role) n++;
|
|
@@ -766,6 +966,10 @@ function isWebOrigin(origin) {
|
|
|
766
966
|
const value = String(origin || '').trim();
|
|
767
967
|
return 'null' === value.toLowerCase() || /^https?:\/\//i.test(value);
|
|
768
968
|
}
|
|
969
|
+
function isAdmittedOrigin(origin, viewerOrigin) {
|
|
970
|
+
if (!isWebOrigin(origin)) return true;
|
|
971
|
+
return isSameWebOrigin(origin, viewerOrigin);
|
|
972
|
+
}
|
|
769
973
|
function startControlServer(options) {
|
|
770
974
|
const { broker } = options;
|
|
771
975
|
const host = options.host ?? '127.0.0.1';
|
|
@@ -775,12 +979,14 @@ function startControlServer(options) {
|
|
|
775
979
|
host,
|
|
776
980
|
port: options.port ?? 0,
|
|
777
981
|
path,
|
|
778
|
-
verifyClient: (info)
|
|
982
|
+
verifyClient: (info)=>isAdmittedOrigin(info.origin, options.viewerOrigin)
|
|
779
983
|
});
|
|
780
984
|
wss.on('error', reject);
|
|
781
|
-
wss.on('connection', (socket)=>{
|
|
985
|
+
wss.on('connection', (socket, request)=>{
|
|
986
|
+
const origin = request?.headers?.origin;
|
|
782
987
|
const conn = {
|
|
783
988
|
id: `c${++connSeq}`,
|
|
989
|
+
origin: 'string' == typeof origin ? origin : void 0,
|
|
784
990
|
send (frame) {
|
|
785
991
|
if (socket.readyState !== WebSocket.OPEN) return;
|
|
786
992
|
if (socket.bufferedAmount > SLOW_CONSUMER_BYTES) {
|
|
@@ -909,6 +1115,35 @@ class PortManager {
|
|
|
909
1115
|
this.currentInstance = null;
|
|
910
1116
|
}
|
|
911
1117
|
}
|
|
1118
|
+
function createResponseDataRepair(ref) {
|
|
1119
|
+
return (req, res, data, byteLength)=>{
|
|
1120
|
+
const untouched = {
|
|
1121
|
+
data,
|
|
1122
|
+
byteLength
|
|
1123
|
+
};
|
|
1124
|
+
if (0 !== byteLength) return untouched;
|
|
1125
|
+
if (!data || Buffer.isBuffer(data)) return untouched;
|
|
1126
|
+
if (req.headers.range || 206 === res.statusCode) return untouched;
|
|
1127
|
+
const outputPath = ref.outputPath();
|
|
1128
|
+
const outputFileSystem = ref.outputFileSystem();
|
|
1129
|
+
if (!outputPath || 'function' != typeof outputFileSystem?.readFileSync) return untouched;
|
|
1130
|
+
const pathname = decodeURIComponent(String(req.url || '').split('?')[0].split('#')[0]);
|
|
1131
|
+
const filename = __rspack_external_node_path_806ed179.join(outputPath, pathname);
|
|
1132
|
+
if (!filename.startsWith(__rspack_external_node_path_806ed179.join(outputPath, __rspack_external_node_path_806ed179.sep))) return untouched;
|
|
1133
|
+
let buffer;
|
|
1134
|
+
try {
|
|
1135
|
+
buffer = outputFileSystem.readFileSync(filename);
|
|
1136
|
+
} catch {
|
|
1137
|
+
return untouched;
|
|
1138
|
+
}
|
|
1139
|
+
if (0 === buffer.length) return untouched;
|
|
1140
|
+
if ('function' == typeof data.destroy) data.destroy();
|
|
1141
|
+
return {
|
|
1142
|
+
data: buffer,
|
|
1143
|
+
byteLength: buffer.length
|
|
1144
|
+
};
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
912
1147
|
function shouldWriteAssetToDisk(filePath) {
|
|
913
1148
|
if (/(?:^|[/\\])\.\.(?:[/\\]|$)/.test(filePath)) return false;
|
|
914
1149
|
return !/(?:^|[/\\])manifest\.json$/i.test(filePath);
|
|
@@ -1124,6 +1359,8 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1124
1359
|
process.env.EXTENSION_DEV_SERVER_PORT = String(port);
|
|
1125
1360
|
process.env.EXTENSION_DEV_SERVER_PATH = '/ws';
|
|
1126
1361
|
const browserName = String(devOptions.browser || 'chromium');
|
|
1362
|
+
const emulatorLane = isEmulatorBrowser(browserName);
|
|
1363
|
+
const emulatorOrigin = emulatorLane ? resolveEmulatorOrigin() : null;
|
|
1127
1364
|
const primaryDistPath = getDistPath(asAbsolute(packageJsonDir), browserName);
|
|
1128
1365
|
const bridgeLogsAbsPath = logsPath(packageJsonDir, browserName);
|
|
1129
1366
|
ensureSessionArtifactsIgnoreFile(packageJsonDir);
|
|
@@ -1146,7 +1383,8 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1146
1383
|
const bridgeBroker = new BridgeBroker({
|
|
1147
1384
|
instanceId: currentInstance.instanceId,
|
|
1148
1385
|
runId: sessionRunId,
|
|
1149
|
-
engine: isGeckoBasedBrowser(browserName) ? 'firefox' : isWebkitBasedBrowser(browserName) ? 'webkit' : 'chromium',
|
|
1386
|
+
engine: emulatorLane ? 'emulator' : isGeckoBasedBrowser(browserName) ? 'firefox' : isWebkitBasedBrowser(browserName) ? 'webkit' : 'chromium',
|
|
1387
|
+
viewerOrigin: emulatorOrigin,
|
|
1150
1388
|
ring: new LogRingBuffer(),
|
|
1151
1389
|
file: bridgeLogFile,
|
|
1152
1390
|
allowControl,
|
|
@@ -1195,13 +1433,15 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1195
1433
|
controlServer = await startControlServer({
|
|
1196
1434
|
broker: bridgeBroker,
|
|
1197
1435
|
host: devServerHost,
|
|
1198
|
-
port: preferredControlPort ?? 0
|
|
1436
|
+
port: preferredControlPort ?? 0,
|
|
1437
|
+
viewerOrigin: emulatorOrigin
|
|
1199
1438
|
});
|
|
1200
1439
|
} catch (error) {
|
|
1201
1440
|
if (null == preferredControlPort) throw error;
|
|
1202
1441
|
controlServer = await startControlServer({
|
|
1203
1442
|
broker: bridgeBroker,
|
|
1204
|
-
host: devServerHost
|
|
1443
|
+
host: devServerHost,
|
|
1444
|
+
viewerOrigin: emulatorOrigin
|
|
1205
1445
|
});
|
|
1206
1446
|
}
|
|
1207
1447
|
bridgeControlPort = controlServer.port;
|
|
@@ -1213,6 +1453,16 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1213
1453
|
}
|
|
1214
1454
|
process.env.EXTENSION_INSTANCE_ID = currentInstance.instanceId;
|
|
1215
1455
|
process.env.EXTENSION_CONTROL_PORT = null != bridgeControlPort ? String(bridgeControlPort) : '';
|
|
1456
|
+
const emulatorFiles = emulatorLane ? createEmulatorFileIndexHolder(currentInstance.instanceId) : null;
|
|
1457
|
+
const emulatorViewer = emulatorLane && emulatorOrigin ? buildEmulatorViewerUrl({
|
|
1458
|
+
origin: emulatorOrigin,
|
|
1459
|
+
host: connectableHost,
|
|
1460
|
+
port,
|
|
1461
|
+
controlPort: bridgeControlPort,
|
|
1462
|
+
controlPath: CONTROL_WS_PATH,
|
|
1463
|
+
instanceId: currentInstance.instanceId
|
|
1464
|
+
}) : null;
|
|
1465
|
+
if (emulatorViewer && launchedPlugin && 'function' == typeof launchedPlugin.setEmulatorViewerUrl) launchedPlugin.setEmulatorViewerUrl(emulatorViewer);
|
|
1216
1466
|
process.once('exit', ()=>{
|
|
1217
1467
|
try {
|
|
1218
1468
|
bridgeLogFile.close();
|
|
@@ -1281,6 +1531,7 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1281
1531
|
port
|
|
1282
1532
|
});
|
|
1283
1533
|
if (shouldWarnPortConflict(devOptions.port, port)) humanLine(portInUse(Number(devOptions.port), port));
|
|
1534
|
+
let activeCompiler = null;
|
|
1284
1535
|
const serverConfig = {
|
|
1285
1536
|
host: devServerHost,
|
|
1286
1537
|
allowedHosts: 'all',
|
|
@@ -1293,7 +1544,11 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1293
1544
|
writeToDisk: shouldWriteAssetToDisk,
|
|
1294
1545
|
stats: {
|
|
1295
1546
|
all: false
|
|
1296
|
-
}
|
|
1547
|
+
},
|
|
1548
|
+
modifyResponseData: createResponseDataRepair({
|
|
1549
|
+
outputPath: ()=>activeCompiler?.options?.output?.path,
|
|
1550
|
+
outputFileSystem: ()=>activeCompiler?.outputFileSystem
|
|
1551
|
+
})
|
|
1297
1552
|
},
|
|
1298
1553
|
watchFiles: {
|
|
1299
1554
|
paths: [
|
|
@@ -1317,6 +1572,12 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1317
1572
|
headers: {
|
|
1318
1573
|
'Access-Control-Allow-Origin': '*'
|
|
1319
1574
|
},
|
|
1575
|
+
...emulatorFiles ? {
|
|
1576
|
+
setupMiddlewares: (...args)=>[
|
|
1577
|
+
createEmulatorFilesMiddlewareEntry(emulatorFiles, args[1]),
|
|
1578
|
+
...args[0]
|
|
1579
|
+
]
|
|
1580
|
+
} : {},
|
|
1320
1581
|
port,
|
|
1321
1582
|
hot: true,
|
|
1322
1583
|
liveReload: true
|
|
@@ -1327,6 +1588,7 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1327
1588
|
const customWebpackConfig = await loadCustomConfig(packageJsonDir);
|
|
1328
1589
|
const compilerConfig = applySplitChunksGuard(merge(customWebpackConfig(baseConfig), {}));
|
|
1329
1590
|
const compiler = rspack(compilerConfig);
|
|
1591
|
+
activeCompiler = compiler;
|
|
1330
1592
|
const uninstallManifestGuard = installManifestDiskWriteGuard(manifestOutputPath);
|
|
1331
1593
|
const releaseOutputFsGuard = suppressManifestOutputWrites(compiler, manifestOutputPath);
|
|
1332
1594
|
if (!extendedOptions.browsersPlugin && compiler?.hooks?.watchRun) {
|
|
@@ -1354,6 +1616,15 @@ async function dev_server_devServer(projectStructure, devOptions) {
|
|
|
1354
1616
|
});
|
|
1355
1617
|
});
|
|
1356
1618
|
}
|
|
1619
|
+
if (emulatorFiles) attachEmulatorFileIndex(compiler, emulatorFiles);
|
|
1620
|
+
if (emulatorViewer && !opts.isRestart && devOptions.noBrowser) {
|
|
1621
|
+
let printedViewer = false;
|
|
1622
|
+
compiler.hooks.done.tap('extjs-emulator-viewer-url', (stats)=>{
|
|
1623
|
+
if (printedViewer || stats?.hasErrors?.()) return;
|
|
1624
|
+
printedViewer = true;
|
|
1625
|
+
humanLine(emulatorViewerUrl(emulatorViewer));
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1357
1628
|
attachLifecycleStream(compiler, lifecycle);
|
|
1358
1629
|
setupCompilerLifecycleHooks(compiler);
|
|
1359
1630
|
if (!opts.isRestart && devOptions.noBrowser) setupNoBrowserBannerOnFirstDone({
|
|
@@ -4,7 +4,7 @@ import node_path from "node:path";
|
|
|
4
4
|
import { parse } from "es-module-lexer";
|
|
5
5
|
import { validate } from "schema-utils";
|
|
6
6
|
import { filterKeysForThisBrowser, reservedScriptsFolder } from "./672~0.mjs";
|
|
7
|
-
import { stripBom, findNearestProjectManifestSync } from "./
|
|
7
|
+
import { stripBom, findNearestProjectManifestSync } from "./474~0.mjs";
|
|
8
8
|
import { canonicalizeDir, canonicalizeResourcePath } from "./938~0.mjs";
|
|
9
9
|
import { getCanonicalContentScriptEntryName, CANONICAL_CONTENT_SCRIPT_ENTRY_PREFIX, getContentScriptCssProbeMarker } from "./640~0.mjs";
|
|
10
10
|
import { EXTENSION_ROOT_PLACEHOLDER } from "./747~0.mjs";
|
|
@@ -4,7 +4,7 @@ import node_path from "node:path";
|
|
|
4
4
|
import { parse } from "es-module-lexer";
|
|
5
5
|
import { validate } from "schema-utils";
|
|
6
6
|
import { filterKeysForThisBrowser, reservedScriptsFolder } from "./672~0.mjs";
|
|
7
|
-
import { stripBom, findNearestProjectManifestSync } from "./
|
|
7
|
+
import { stripBom, findNearestProjectManifestSync } from "./474~0.mjs";
|
|
8
8
|
import { canonicalizeDir, canonicalizeResourcePath } from "./938~0.mjs";
|
|
9
9
|
import { getCanonicalContentScriptEntryName, CANONICAL_CONTENT_SCRIPT_ENTRY_PREFIX, getContentScriptCssProbeMarker } from "./640~0.mjs";
|
|
10
10
|
import { EXTENSION_ROOT_PLACEHOLDER } from "./747~0.mjs";
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export declare const GECKO_BASED_BROWSERS: string[];
|
|
|
4
4
|
export declare const WEBKIT_BASED_BROWSERS: string[];
|
|
5
5
|
export declare const CHROMIUM_FAMILY_ALIASES: string[];
|
|
6
6
|
export declare const GECKO_FAMILY_ALIASES: string[];
|
|
7
|
+
export declare const EMULATOR_BROWSER = "chromium-emulator";
|
|
8
|
+
export declare function isEmulatorLaneEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
9
|
+
export declare function isEmulatorBrowser(browser: unknown): boolean;
|
|
7
10
|
export declare const SUPPORTED_BROWSERS: string[];
|
|
8
11
|
export declare const SUPPORTED_PACKAGE_MANAGERS: readonly ['npm', 'pnpm', 'yarn', 'bun', 'deno'];
|
|
9
12
|
export declare const SUPPORTED_RUNTIMES: readonly ['node', 'deno', 'bun'];
|
package/dist/lib/paths.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { ProjectStructure } from './project.js';
|
|
|
2
2
|
export type AbsolutePath = string & {
|
|
3
3
|
readonly __brand: 'AbsolutePath';
|
|
4
4
|
};
|
|
5
|
-
export type BrowserInput = 'chrome' | 'edge' | 'chromium' | 'firefox' | 'brave' | 'opera' | 'vivaldi' | 'yandex' | 'waterfox' | 'librewolf' | 'zen' | 'floorp' | 'chromium-based' | 'gecko-based' | 'firefox-based' | 'safari' | 'webkit-based' | undefined;
|
|
6
|
-
export type NormalizedBrowser = 'chrome' | 'edge' | 'chromium' | 'firefox' | 'brave' | 'opera' | 'vivaldi' | 'yandex' | 'waterfox' | 'librewolf' | 'zen' | 'floorp' | 'chromium-based' | 'gecko-based' | 'safari' | 'webkit-based';
|
|
5
|
+
export type BrowserInput = 'chrome' | 'edge' | 'chromium' | 'firefox' | 'brave' | 'opera' | 'vivaldi' | 'yandex' | 'waterfox' | 'librewolf' | 'zen' | 'floorp' | 'chromium-based' | 'gecko-based' | 'firefox-based' | 'safari' | 'webkit-based' | 'chromium-emulator' | undefined;
|
|
6
|
+
export type NormalizedBrowser = 'chrome' | 'edge' | 'chromium' | 'firefox' | 'brave' | 'opera' | 'vivaldi' | 'yandex' | 'waterfox' | 'librewolf' | 'zen' | 'floorp' | 'chromium-based' | 'gecko-based' | 'safari' | 'webkit-based' | 'chromium-emulator';
|
|
7
7
|
export declare function asAbsolute(p: string): AbsolutePath;
|
|
8
8
|
export declare function toPosixPath(p: string): string;
|
|
9
9
|
export declare function collapseHomeDir(value: string): string;
|
|
@@ -47,6 +47,7 @@ export interface BrowserLaunchOptions {
|
|
|
47
47
|
logColor?: boolean;
|
|
48
48
|
logUrl?: string;
|
|
49
49
|
logTab?: number | string;
|
|
50
|
+
emulatorViewerUrl?: string;
|
|
50
51
|
logSink?: BrowserLogSink;
|
|
51
52
|
}
|
|
52
53
|
/** Browser-generated log entry normalized by the launcher's CDP controller. */
|
|
@@ -118,6 +119,7 @@ export declare class BrowsersPlugin implements RunnerPlugin {
|
|
|
118
119
|
private controller;
|
|
119
120
|
private reloadBroker;
|
|
120
121
|
private logSink;
|
|
122
|
+
private emulatorViewerUrl;
|
|
121
123
|
private lastReportedRefusal;
|
|
122
124
|
constructor(options: BrowsersPluginOptions);
|
|
123
125
|
/**
|
|
@@ -127,6 +129,7 @@ export declare class BrowsersPlugin implements RunnerPlugin {
|
|
|
127
129
|
*/
|
|
128
130
|
setReloadBroker(broker: ReloadBroker): void;
|
|
129
131
|
setLogSink(sink: BrowserLogSink): void;
|
|
132
|
+
setEmulatorViewerUrl(url: string): void;
|
|
130
133
|
private retryRefusedExtensionLoad;
|
|
131
134
|
apply(compiler: Compiler): void;
|
|
132
135
|
}
|
package/dist/rspack-config~0.mjs
CHANGED
|
@@ -13,11 +13,10 @@ import node_fs from "node:fs";
|
|
|
13
13
|
import node_path from "node:path";
|
|
14
14
|
import { utils_isUrl, getBaseNode, parseHtml, manifestJsonOutputTarget, getExtname, getBaseHref, isResourceUnderDirs, getAssetsFromHtml, normalizeManifestOutputPath, manifestPageOutputTarget, canonicalizeDir, iconOutputPath, isFromIncludeList, htmlStaticAssetOutputName, isSpecialScheme, resolveStaticAttributeName, getHtmlPageDeclaredAssetPath, themeImageOutputPath, themeIconOutputPath, applyRewrittenStaticUrl, toResourceKey, cleanLeading, getFilePath, resolveAbsoluteFsPath, cleanAssetUrl, isHttpLike, resolveHtmlRefPath } from "./938~0.mjs";
|
|
15
15
|
import { prefix as messaging_prefix, isDebug } from "./852~0.mjs";
|
|
16
|
-
import { isChromiumBasedBrowser, CHROMIUM_FAMILY_ALIASES,
|
|
16
|
+
import { GECKO_FAMILY_ALIASES, isEmulatorBrowser, isGeckoBasedBrowser, findNearestProjectManifestSync, readProjectDependencies, isChromiumBasedBrowser, CHROMIUM_FAMILY_ALIASES, stripBom, PROJECT_MANIFEST_FILENAMES, parseJsonSafe, isWebkitBasedBrowser } from "./474~0.mjs";
|
|
17
17
|
import { maybeUsePreact, isUsingTypeScript, jsFrameworksIntegrationsEnabled, maybeUseReact, isUsingVue, classifyEntrySurface, ensureTypeScriptConfig, resolveDevelopInstallRoot, loadLoaderOptions, getUserTypeScriptConfigFile, svelteCompilerRuntimeMismatch, isUsingIntegration as messages_isUsingIntegration, maybeUseVue, maybeUseSolid, jsFrameworksHmrSummary, humanLine, ensureOptionalContractPackageResolved, jsFrameworksConfigsDetected, recordZipArtifact, hasDependency, resolveDevelopDistFile, isUsingJsxFramework, getJsxImportSource, swcParserForFile, isUsingReact, defaultSplitChunks } from "./840~0.mjs";
|
|
18
18
|
import { bundlerFatalError, bundlerRecompiling, browserRunnerDisabled, PlaywrightPlugin, publicFolderShadowed, resolveCompanionExtensionDirs, specialFoldersSetupSummary, noEntrypointsDetected, serverRestartRequiredFromSpecialFolderMessageOnly, specialFolderChangeDetected, spacerLine, messages_ready, getPreloadedEnvKeys, publicMustBeAtProjectRoot, computeExtensionsToLoad, getSpecialFoldersDataForCompiler } from "./832~0.mjs";
|
|
19
19
|
import { renderStatsBlocks, makeSanitizedConsole } from "./stats-handler~0.mjs";
|
|
20
|
-
import { stripBom, findNearestProjectManifestSync, PROJECT_MANIFEST_FILENAMES, parseJsonSafe, readProjectDependencies } from "./731~0.mjs";
|
|
21
20
|
import { EXTENSIONJS_CONTENT_SCRIPT_LAYER, getCanonicalContentScriptEntryName, parseCanonicalContentScriptAsset, CONTENT_SCRIPT_CSS_PROBE_MARKER_PREFIX, createContentScriptCssProbeMarkerPattern, getCanonicalContentScriptJsAssetName, getCanonicalContentScriptCssAssetName, isCanonicalContentScriptAsset } from "./640~0.mjs";
|
|
22
21
|
import { getURLDependencyMissing, findDroppedVendorKeys, isStaticThemeSource, workerStartedFromPageContext, importScriptsDependencyMissing, filterKeysForThisBrowser, findPrefixedManifestVersionKeys, injectedCompiledSourceLiteral, staticImportDependencyMissing, entrySplitAcrossInitialFiles, fetchedFileDependencyMissing, isStaticTheme, compiledSourceSpelling, injectedFileDependencyMissing, isValidManifestVersion, runtimeSetSurfaceDependencyMissing } from "./672~0.mjs";
|
|
23
22
|
import { packagingSourceFiles, debugBrowser, debugExtensionsToLoad, treeWithSourceFiles, debugOutputPath, manifestInvalidJson, getDirs, asAbsolute, treeWithDistFilesBrowser, packagingDistributionFiles, treeWithSourceAndDistFiles, toPosixPath as paths_toPosixPath, debugContextPath, noCompanionExtensionsResolved } from "./950~0.mjs";
|
|
@@ -7041,9 +7040,11 @@ class ReloadPlugin {
|
|
|
7041
7040
|
browser: this.browser
|
|
7042
7041
|
}).apply(compiler);
|
|
7043
7042
|
new InjectScriptsReplayShim().apply(compiler);
|
|
7044
|
-
if (isChromiumBasedBrowser(String(this.browser))) new SetupDevContentScripts().apply(compiler);
|
|
7045
|
-
|
|
7046
|
-
|
|
7043
|
+
if (isChromiumBasedBrowser(String(this.browser)) && !isEmulatorBrowser(this.browser)) new SetupDevContentScripts().apply(compiler);
|
|
7044
|
+
if (!isEmulatorBrowser(this.browser)) {
|
|
7045
|
+
new InjectBridgeProducer().apply(compiler);
|
|
7046
|
+
new InjectBridgeRelay().apply(compiler);
|
|
7047
|
+
}
|
|
7047
7048
|
new PruneStaleHotUpdates().apply(compiler);
|
|
7048
7049
|
}
|
|
7049
7050
|
}
|
|
@@ -8786,6 +8787,21 @@ class WasmPlugin {
|
|
|
8786
8787
|
this.ensureWasmResolution(compiler, projectRoot);
|
|
8787
8788
|
}
|
|
8788
8789
|
}
|
|
8790
|
+
function filesOf(value) {
|
|
8791
|
+
if (Array.isArray(value)) return value;
|
|
8792
|
+
return value ? [
|
|
8793
|
+
value
|
|
8794
|
+
] : [];
|
|
8795
|
+
}
|
|
8796
|
+
function omitOwnedPages(pages, owned) {
|
|
8797
|
+
const ownedFiles = new Set(Object.values(owned).flatMap(filesOf).map((file)=>__rspack_external_node_path_806ed179.resolve(file)));
|
|
8798
|
+
const next = {};
|
|
8799
|
+
for (const [name, value] of Object.entries(pages || {})){
|
|
8800
|
+
const files = filesOf(value);
|
|
8801
|
+
if (!(files.length > 0 && files.every((file)=>ownedFiles.has(__rspack_external_node_path_806ed179.resolve(file))))) next[name] = value;
|
|
8802
|
+
}
|
|
8803
|
+
return next;
|
|
8804
|
+
}
|
|
8789
8805
|
const COMPILED_SIBLING_EXTENSIONS = [
|
|
8790
8806
|
'.ts',
|
|
8791
8807
|
'.mts',
|
|
@@ -15129,15 +15145,18 @@ class plugin_web_extension_WebExtensionPlugin {
|
|
|
15129
15145
|
...manifestFieldsData.scripts
|
|
15130
15146
|
}
|
|
15131
15147
|
}).apply(compiler);
|
|
15148
|
+
const ownedPages = {
|
|
15149
|
+
...manifestFieldsData.html,
|
|
15150
|
+
...discoverDevtoolsPanelPages(manifestPath, this.browser),
|
|
15151
|
+
...settingsOverridesStartupPages(manifestPath, this.browser)
|
|
15152
|
+
};
|
|
15132
15153
|
new HtmlPlugin({
|
|
15133
15154
|
devSession: this.devSession,
|
|
15134
15155
|
manifestPath,
|
|
15135
15156
|
browser: this.browser,
|
|
15136
15157
|
includeList: {
|
|
15137
|
-
...
|
|
15138
|
-
...
|
|
15139
|
-
...settingsOverridesStartupPages(manifestPath, this.browser),
|
|
15140
|
-
...specialFoldersData.pages
|
|
15158
|
+
...ownedPages,
|
|
15159
|
+
...omitOwnedPages(specialFoldersData.pages, ownedPages)
|
|
15141
15160
|
}
|
|
15142
15161
|
}).apply(compiler);
|
|
15143
15162
|
new ScriptsPlugin({
|
package/dist/types.d.ts
CHANGED
|
@@ -65,7 +65,7 @@ export interface JsFramework {
|
|
|
65
65
|
import type { Configuration } from '@rspack/core';
|
|
66
66
|
import type { SafariPackageSummary } from './lib/build-summary.js';
|
|
67
67
|
import type { CompanionExtensionsConfig } from './plugin-special-folders/folder-extensions/types.js';
|
|
68
|
-
export type BrowserType = 'chrome' | 'edge' | 'firefox' | 'chromium' | 'brave' | 'opera' | 'vivaldi' | 'yandex' | 'waterfox' | 'librewolf' | 'zen' | 'floorp' | 'chromium-based' | 'gecko-based' | 'firefox-based' | 'safari' | 'webkit-based';
|
|
68
|
+
export type BrowserType = 'chrome' | 'edge' | 'firefox' | 'chromium' | 'brave' | 'opera' | 'vivaldi' | 'yandex' | 'waterfox' | 'librewolf' | 'zen' | 'floorp' | 'chromium-based' | 'gecko-based' | 'firefox-based' | 'safari' | 'webkit-based' | 'chromium-emulator';
|
|
69
69
|
export interface BrowserOptionsBase {
|
|
70
70
|
noOpen?: boolean;
|
|
71
71
|
profile?: string | false;
|
package/package.json
CHANGED
package/dist/331~0.mjs
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
|
-
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
3
|
-
__rspack_external_node_path_806ed179.join(process.cwd(), 'node_modules/extension-develop/dist/certs');
|
|
4
|
-
const CHROMIUM_BASED_BROWSERS = [
|
|
5
|
-
'chrome',
|
|
6
|
-
'edge',
|
|
7
|
-
'brave',
|
|
8
|
-
'opera',
|
|
9
|
-
'vivaldi',
|
|
10
|
-
'yandex'
|
|
11
|
-
];
|
|
12
|
-
const GECKO_BASED_BROWSERS = [
|
|
13
|
-
'firefox',
|
|
14
|
-
'waterfox',
|
|
15
|
-
'librewolf',
|
|
16
|
-
'zen',
|
|
17
|
-
'floorp'
|
|
18
|
-
];
|
|
19
|
-
const WEBKIT_BASED_BROWSERS = [
|
|
20
|
-
'safari'
|
|
21
|
-
];
|
|
22
|
-
const CHROMIUM_FAMILY_ALIASES = [
|
|
23
|
-
'chromium',
|
|
24
|
-
'chrome',
|
|
25
|
-
'edge',
|
|
26
|
-
'chromium-based'
|
|
27
|
-
];
|
|
28
|
-
const GECKO_FAMILY_ALIASES = [
|
|
29
|
-
'firefox',
|
|
30
|
-
'gecko-based'
|
|
31
|
-
];
|
|
32
|
-
[
|
|
33
|
-
...CHROMIUM_BASED_BROWSERS,
|
|
34
|
-
...GECKO_BASED_BROWSERS
|
|
35
|
-
];
|
|
36
|
-
function isChromiumBasedBrowser(browser) {
|
|
37
|
-
return CHROMIUM_BASED_BROWSERS.includes(browser) || String(browser).includes('chromium');
|
|
38
|
-
}
|
|
39
|
-
function isGeckoBasedBrowser(browser) {
|
|
40
|
-
return GECKO_BASED_BROWSERS.includes(browser) || String(browser).includes('gecko') || String(browser).includes('firefox');
|
|
41
|
-
}
|
|
42
|
-
function isWebkitBasedBrowser(browser) {
|
|
43
|
-
return WEBKIT_BASED_BROWSERS.includes(browser) || String(browser).includes('webkit');
|
|
44
|
-
}
|
|
45
|
-
export { CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, isChromiumBasedBrowser, isGeckoBasedBrowser, isWebkitBasedBrowser };
|