react-native-ai-debugger 2.12.2 → 2.12.4
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 +15 -1
- package/build/__tests__/unit/autoReconnectOptOut.test.js +3 -0
- package/build/__tests__/unit/autoReconnectOptOut.test.js.map +1 -1
- package/build/__tests__/unit/cdpCommand.test.d.ts +2 -0
- package/build/__tests__/unit/cdpCommand.test.d.ts.map +1 -0
- package/build/__tests__/unit/cdpCommand.test.js +84 -0
- package/build/__tests__/unit/cdpCommand.test.js.map +1 -0
- package/build/__tests__/unit/chromium.test.d.ts +2 -0
- package/build/__tests__/unit/chromium.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromium.test.js +118 -0
- package/build/__tests__/unit/chromium.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDevice.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDevice.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDevice.test.js +115 -0
- package/build/__tests__/unit/chromiumDevice.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.js +71 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.js +100 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDialogs.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDialogs.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDialogs.test.js +167 -0
- package/build/__tests__/unit/chromiumDialogs.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDiscovery.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDiscovery.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDiscovery.test.js +302 -0
- package/build/__tests__/unit/chromiumDiscovery.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDom.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDom.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDom.test.js +119 -0
- package/build/__tests__/unit/chromiumDom.test.js.map +1 -0
- package/build/__tests__/unit/chromiumGate.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumGate.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumGate.test.js +149 -0
- package/build/__tests__/unit/chromiumGate.test.js.map +1 -0
- package/build/__tests__/unit/chromiumInput.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumInput.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumInput.test.js +113 -0
- package/build/__tests__/unit/chromiumInput.test.js.map +1 -0
- package/build/__tests__/unit/chromiumKeys.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumKeys.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumKeys.test.js +26 -0
- package/build/__tests__/unit/chromiumKeys.test.js.map +1 -0
- package/build/__tests__/unit/chromiumScreen.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumScreen.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumScreen.test.js +390 -0
- package/build/__tests__/unit/chromiumScreen.test.js.map +1 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.js +26 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.js.map +1 -0
- package/build/__tests__/unit/connectionGaps.test.d.ts +2 -0
- package/build/__tests__/unit/connectionGaps.test.d.ts.map +1 -0
- package/build/__tests__/unit/connectionGaps.test.js +14 -0
- package/build/__tests__/unit/connectionGaps.test.js.map +1 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.d.ts +2 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.d.ts.map +1 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.js +25 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.js.map +1 -0
- package/build/__tests__/unit/deviceResolver.test.js +9 -0
- package/build/__tests__/unit/deviceResolver.test.js.map +1 -1
- package/build/__tests__/unit/electronLaunch.test.d.ts +2 -0
- package/build/__tests__/unit/electronLaunch.test.d.ts.map +1 -0
- package/build/__tests__/unit/electronLaunch.test.js +165 -0
- package/build/__tests__/unit/electronLaunch.test.js.map +1 -0
- package/build/__tests__/unit/fiberRoots.test.d.ts +2 -0
- package/build/__tests__/unit/fiberRoots.test.d.ts.map +1 -0
- package/build/__tests__/unit/fiberRoots.test.js +95 -0
- package/build/__tests__/unit/fiberRoots.test.js.map +1 -0
- package/build/__tests__/unit/fiberRootsDrift.test.d.ts +2 -0
- package/build/__tests__/unit/fiberRootsDrift.test.d.ts.map +1 -0
- package/build/__tests__/unit/fiberRootsDrift.test.js +23 -0
- package/build/__tests__/unit/fiberRootsDrift.test.js.map +1 -0
- package/build/__tests__/unit/hostAddress.test.d.ts +2 -0
- package/build/__tests__/unit/hostAddress.test.d.ts.map +1 -0
- package/build/__tests__/unit/hostAddress.test.js +38 -0
- package/build/__tests__/unit/hostAddress.test.js.map +1 -0
- package/build/__tests__/unit/inputTargetWrapperTestID.test.d.ts +2 -0
- package/build/__tests__/unit/inputTargetWrapperTestID.test.d.ts.map +1 -0
- package/build/__tests__/unit/inputTargetWrapperTestID.test.js +73 -0
- package/build/__tests__/unit/inputTargetWrapperTestID.test.js.map +1 -0
- package/build/__tests__/unit/iosTerminateNotRunning.test.d.ts +2 -0
- package/build/__tests__/unit/iosTerminateNotRunning.test.d.ts.map +1 -0
- package/build/__tests__/unit/iosTerminateNotRunning.test.js +39 -0
- package/build/__tests__/unit/iosTerminateNotRunning.test.js.map +1 -0
- package/build/__tests__/unit/measureComponent.test.js +1 -1
- package/build/__tests__/unit/measureComponent.test.js.map +1 -1
- package/build/__tests__/unit/navigation.test.js +20 -0
- package/build/__tests__/unit/navigation.test.js.map +1 -1
- package/build/__tests__/unit/networkInterceptorFetchMock.test.d.ts +2 -0
- package/build/__tests__/unit/networkInterceptorFetchMock.test.d.ts.map +1 -0
- package/build/__tests__/unit/networkInterceptorFetchMock.test.js +90 -0
- package/build/__tests__/unit/networkInterceptorFetchMock.test.js.map +1 -0
- package/build/__tests__/unit/networkInterceptorXhr.test.js +12 -0
- package/build/__tests__/unit/networkInterceptorXhr.test.js.map +1 -1
- package/build/__tests__/unit/networkMockTool.test.js +12 -1
- package/build/__tests__/unit/networkMockTool.test.js.map +1 -1
- package/build/__tests__/unit/pressKeyMobile.test.d.ts +2 -0
- package/build/__tests__/unit/pressKeyMobile.test.d.ts.map +1 -0
- package/build/__tests__/unit/pressKeyMobile.test.js +63 -0
- package/build/__tests__/unit/pressKeyMobile.test.js.map +1 -0
- package/build/__tests__/unit/reloadAppAutoConnect.test.js +4 -1
- package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -1
- package/build/__tests__/unit/tapAndroidSerial.test.js +16 -0
- package/build/__tests__/unit/tapAndroidSerial.test.js.map +1 -1
- package/build/__tests__/unit/textEntry.test.js +9 -0
- package/build/__tests__/unit/textEntry.test.js.map +1 -1
- package/build/core/android.d.ts +10 -0
- package/build/core/android.d.ts.map +1 -1
- package/build/core/android.js +17 -0
- package/build/core/android.js.map +1 -1
- package/build/core/appContext.d.ts.map +1 -1
- package/build/core/appContext.js +11 -13
- package/build/core/appContext.js.map +1 -1
- package/build/core/appDetection.d.ts.map +1 -1
- package/build/core/appDetection.js +7 -4
- package/build/core/appDetection.js.map +1 -1
- package/build/core/cdpCommand.d.ts +4 -0
- package/build/core/cdpCommand.d.ts.map +1 -0
- package/build/core/cdpCommand.js +58 -0
- package/build/core/cdpCommand.js.map +1 -0
- package/build/core/chromium.d.ts +157 -0
- package/build/core/chromium.d.ts.map +1 -0
- package/build/core/chromium.js +480 -0
- package/build/core/chromium.js.map +1 -0
- package/build/core/chromiumCapabilities.d.ts +11 -0
- package/build/core/chromiumCapabilities.d.ts.map +1 -0
- package/build/core/chromiumCapabilities.js +35 -0
- package/build/core/chromiumCapabilities.js.map +1 -0
- package/build/core/chromiumDialogAnswer.d.ts +11 -0
- package/build/core/chromiumDialogAnswer.d.ts.map +1 -0
- package/build/core/chromiumDialogAnswer.js +61 -0
- package/build/core/chromiumDialogAnswer.js.map +1 -0
- package/build/core/chromiumDialogs.d.ts +46 -0
- package/build/core/chromiumDialogs.d.ts.map +1 -0
- package/build/core/chromiumDialogs.js +88 -0
- package/build/core/chromiumDialogs.js.map +1 -0
- package/build/core/chromiumScreen.d.ts +97 -0
- package/build/core/chromiumScreen.d.ts.map +1 -0
- package/build/core/chromiumScreen.js +498 -0
- package/build/core/chromiumScreen.js.map +1 -0
- package/build/core/componentSearch.d.ts.map +1 -1
- package/build/core/componentSearch.js +7 -26
- package/build/core/componentSearch.js.map +1 -1
- package/build/core/componentSource.d.ts.map +1 -1
- package/build/core/componentSource.js +3 -11
- package/build/core/componentSource.js.map +1 -1
- package/build/core/componentTree.d.ts.map +1 -1
- package/build/core/componentTree.js +4 -18
- package/build/core/componentTree.js.map +1 -1
- package/build/core/connection.d.ts +13 -0
- package/build/core/connection.d.ts.map +1 -1
- package/build/core/connection.js +99 -18
- package/build/core/connection.js.map +1 -1
- package/build/core/connectionState.d.ts +2 -1
- package/build/core/connectionState.d.ts.map +1 -1
- package/build/core/connectionState.js +3 -0
- package/build/core/connectionState.js.map +1 -1
- package/build/core/deviceResolver.d.ts.map +1 -1
- package/build/core/deviceResolver.js +8 -5
- package/build/core/deviceResolver.js.map +1 -1
- package/build/core/electronLaunch.d.ts +25 -0
- package/build/core/electronLaunch.d.ts.map +1 -0
- package/build/core/electronLaunch.js +113 -0
- package/build/core/electronLaunch.js.map +1 -0
- package/build/core/errors.d.ts +1 -1
- package/build/core/errors.d.ts.map +1 -1
- package/build/core/errors.js.map +1 -1
- package/build/core/guides.d.ts.map +1 -1
- package/build/core/guides.js +17 -8
- package/build/core/guides.js.map +1 -1
- package/build/core/hostAddress.d.ts +6 -0
- package/build/core/hostAddress.d.ts.map +1 -0
- package/build/core/hostAddress.js +32 -0
- package/build/core/hostAddress.js.map +1 -0
- package/build/core/injected/fiberRoots.d.ts +2 -0
- package/build/core/injected/fiberRoots.d.ts.map +1 -0
- package/build/core/injected/fiberRoots.js +60 -0
- package/build/core/injected/fiberRoots.js.map +1 -0
- package/build/core/inputTarget.d.ts.map +1 -1
- package/build/core/inputTarget.js +49 -10
- package/build/core/inputTarget.js.map +1 -1
- package/build/core/inspector.d.ts.map +1 -1
- package/build/core/inspector.js +6 -22
- package/build/core/inspector.js.map +1 -1
- package/build/core/ios.d.ts +12 -0
- package/build/core/ios.d.ts.map +1 -1
- package/build/core/ios.js +40 -1
- package/build/core/ios.js.map +1 -1
- package/build/core/jsExecute.d.ts.map +1 -1
- package/build/core/jsExecute.js +20 -1
- package/build/core/jsExecute.js.map +1 -1
- package/build/core/measureComponent.d.ts.map +1 -1
- package/build/core/measureComponent.js +4 -8
- package/build/core/measureComponent.js.map +1 -1
- package/build/core/metro.d.ts +20 -1
- package/build/core/metro.d.ts.map +1 -1
- package/build/core/metro.js +146 -9
- package/build/core/metro.js.map +1 -1
- package/build/core/mockRules.d.ts +1 -0
- package/build/core/mockRules.d.ts.map +1 -1
- package/build/core/mockRules.js +8 -0
- package/build/core/mockRules.js.map +1 -1
- package/build/core/nativeLogs.js +1 -1
- package/build/core/nativeLogs.js.map +1 -1
- package/build/core/navigate.d.ts +2 -0
- package/build/core/navigate.d.ts.map +1 -1
- package/build/core/navigate.js +1 -0
- package/build/core/navigate.js.map +1 -1
- package/build/core/navigation.d.ts.map +1 -1
- package/build/core/navigation.js +61 -11
- package/build/core/navigation.js.map +1 -1
- package/build/core/networkInterceptor.d.ts +2 -2
- package/build/core/networkInterceptor.d.ts.map +1 -1
- package/build/core/networkInterceptor.js +98 -4
- package/build/core/networkInterceptor.js.map +1 -1
- package/build/core/pressables.d.ts.map +1 -1
- package/build/core/pressables.js +6 -13
- package/build/core/pressables.js.map +1 -1
- package/build/core/redux.d.ts.map +1 -1
- package/build/core/redux.js +6 -10
- package/build/core/redux.js.map +1 -1
- package/build/core/register.d.ts.map +1 -1
- package/build/core/register.js +5 -2
- package/build/core/register.js.map +1 -1
- package/build/core/rnGlobalsBootstrap.d.ts.map +1 -1
- package/build/core/rnGlobalsBootstrap.js +3 -1
- package/build/core/rnGlobalsBootstrap.js.map +1 -1
- package/build/core/screenLayout.d.ts.map +1 -1
- package/build/core/screenLayout.js +4 -13
- package/build/core/screenLayout.js.map +1 -1
- package/build/core/screenStaleness.d.ts.map +1 -1
- package/build/core/screenStaleness.js +2 -0
- package/build/core/screenStaleness.js.map +1 -1
- package/build/core/screenState.d.ts.map +1 -1
- package/build/core/screenState.js +4 -11
- package/build/core/screenState.js.map +1 -1
- package/build/core/swipeDiagnosis.d.ts.map +1 -1
- package/build/core/swipeDiagnosis.js +3 -10
- package/build/core/swipeDiagnosis.js.map +1 -1
- package/build/core/textEntry.d.ts +1 -1
- package/build/core/textEntry.d.ts.map +1 -1
- package/build/core/textEntry.js +8 -0
- package/build/core/textEntry.js.map +1 -1
- package/build/core/types.d.ts +4 -2
- package/build/core/types.d.ts.map +1 -1
- package/build/pro/chromiumKeys.d.ts +19 -0
- package/build/pro/chromiumKeys.d.ts.map +1 -0
- package/build/pro/chromiumKeys.js +68 -0
- package/build/pro/chromiumKeys.js.map +1 -0
- package/build/pro/chromiumSwipe.d.ts +35 -0
- package/build/pro/chromiumSwipe.d.ts.map +1 -0
- package/build/pro/chromiumSwipe.js +105 -0
- package/build/pro/chromiumSwipe.js.map +1 -0
- package/build/pro/chromiumTap.d.ts +12 -0
- package/build/pro/chromiumTap.d.ts.map +1 -0
- package/build/pro/chromiumTap.js +155 -0
- package/build/pro/chromiumTap.js.map +1 -0
- package/build/pro/tap.d.ts +1 -0
- package/build/pro/tap.d.ts.map +1 -1
- package/build/pro/tap.js +7 -1
- package/build/pro/tap.js.map +1 -1
- package/build/tools/componentTools.d.ts.map +1 -1
- package/build/tools/componentTools.js +31 -3
- package/build/tools/componentTools.js.map +1 -1
- package/build/tools/connectionTools.d.ts.map +1 -1
- package/build/tools/connectionTools.js +66 -28
- package/build/tools/connectionTools.js.map +1 -1
- package/build/tools/deviceTools.d.ts.map +1 -1
- package/build/tools/deviceTools.js +42 -1
- package/build/tools/deviceTools.js.map +1 -1
- package/build/tools/executionTools.d.ts.map +1 -1
- package/build/tools/executionTools.js +6 -2
- package/build/tools/executionTools.js.map +1 -1
- package/build/tools/interactionTools.d.ts.map +1 -1
- package/build/tools/interactionTools.js +151 -8
- package/build/tools/interactionTools.js.map +1 -1
- package/build/tools/navigationTools.d.ts.map +1 -1
- package/build/tools/navigationTools.js +2 -1
- package/build/tools/navigationTools.js.map +1 -1
- package/build/tools/networkTools.d.ts.map +1 -1
- package/build/tools/networkTools.js +20 -5
- package/build/tools/networkTools.js.map +1 -1
- package/build/tools/screenshotTools.d.ts.map +1 -1
- package/build/tools/screenshotTools.js +452 -373
- package/build/tools/screenshotTools.js.map +1 -1
- package/package.json +1 -1
- package/tools.json +29 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, statSync } from "fs";
|
|
4
|
+
import { basename, dirname, join, resolve } from "path";
|
|
5
|
+
import { fetchDevices, isChromiumTarget, isUntitledPage } from "./metro.js";
|
|
6
|
+
import { CONFIG_DIR } from "./paths.js";
|
|
7
|
+
const POLL_MS = 500;
|
|
8
|
+
const TITLE_GRACE_MS = 5000;
|
|
9
|
+
export function findBin(start, name) {
|
|
10
|
+
for (let dir = start;; dir = dirname(dir)) {
|
|
11
|
+
const p = join(dir, "node_modules", ".bin", name);
|
|
12
|
+
if (existsSync(p))
|
|
13
|
+
return p;
|
|
14
|
+
if (dirname(dir) === dir)
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function planElectronLaunch(projectPath, port) {
|
|
19
|
+
const cwd = resolve(projectPath);
|
|
20
|
+
if (/\.(app|asar)(\/|$)/i.test(cwd)) {
|
|
21
|
+
return { error: `${cwd} is a packaged build. execbro never opens a CDP port on a packaged app (anything that reaches the port could run code in it). Pass the project's source folder instead.` };
|
|
22
|
+
}
|
|
23
|
+
if (!existsSync(cwd) || !statSync(cwd).isDirectory()) {
|
|
24
|
+
return { error: `${cwd} is not a directory. Pass the Electron project's source folder, the one with package.json.` };
|
|
25
|
+
}
|
|
26
|
+
const pkgPath = join(cwd, "package.json");
|
|
27
|
+
if (!existsSync(pkgPath))
|
|
28
|
+
return { error: `No package.json in ${cwd}. Pass the Electron project's source folder.` };
|
|
29
|
+
let pkg;
|
|
30
|
+
try {
|
|
31
|
+
pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { error: `${pkgPath} is not valid JSON.` };
|
|
35
|
+
}
|
|
36
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
37
|
+
if (!deps.electron)
|
|
38
|
+
return { error: `${pkg.name ?? cwd} does not depend on electron, so there is nothing to launch.` };
|
|
39
|
+
const runner = deps["electron-vite"] ? "electron-vite" : "electron";
|
|
40
|
+
const cmd = findBin(cwd, runner);
|
|
41
|
+
if (!cmd)
|
|
42
|
+
return { error: `${runner} is declared in package.json but not installed. Run npm install in ${cwd} first.` };
|
|
43
|
+
return runner === "electron-vite"
|
|
44
|
+
? { cmd, args: ["dev", "--remoteDebuggingPort", String(port)], cwd, runner }
|
|
45
|
+
: { cmd, args: [".", `--remote-debugging-port=${port}`], cwd, runner };
|
|
46
|
+
}
|
|
47
|
+
export function devToolsPortFromLog(log) {
|
|
48
|
+
const m = /DevTools listening on ws:\/\/[^:/]+:(\d+)\//.exec(log);
|
|
49
|
+
return m ? Number(m[1]) : null;
|
|
50
|
+
}
|
|
51
|
+
function readLog(path) {
|
|
52
|
+
try {
|
|
53
|
+
return readFileSync(path, "utf8");
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function tail(path, lines = 20) {
|
|
60
|
+
try {
|
|
61
|
+
return readFileSync(path, "utf8").trimEnd().split("\n").slice(-lines).join("\n");
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return "(no log)";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function launchLogPath(logDir, cwd) {
|
|
68
|
+
return join(logDir, `${basename(cwd)}-${createHash("sha1").update(cwd).digest("hex").slice(0, 8)}.log`);
|
|
69
|
+
}
|
|
70
|
+
export async function launchElectron(plan, port, timeoutMs, logDir = join(CONFIG_DIR, "electron")) {
|
|
71
|
+
mkdirSync(logDir, { recursive: true });
|
|
72
|
+
const logPath = launchLogPath(logDir, plan.cwd);
|
|
73
|
+
const fd = openSync(logPath, "w");
|
|
74
|
+
const env = { ...process.env };
|
|
75
|
+
delete env.ELECTRON_RUN_AS_NODE;
|
|
76
|
+
const child = spawn(plan.cmd, plan.args, { cwd: plan.cwd, env, detached: true, stdio: ["ignore", fd, fd] });
|
|
77
|
+
closeSync(fd);
|
|
78
|
+
let exited = null;
|
|
79
|
+
let spawnError = null;
|
|
80
|
+
child.on("exit", (code, signal) => { exited = String(code ?? signal); });
|
|
81
|
+
child.on("error", (e) => { spawnError = e; });
|
|
82
|
+
child.unref();
|
|
83
|
+
const deadline = Date.now() + timeoutMs;
|
|
84
|
+
let firstSeen = null;
|
|
85
|
+
let actual = port;
|
|
86
|
+
let devices = [];
|
|
87
|
+
while (Date.now() < deadline) {
|
|
88
|
+
await new Promise((r) => setTimeout(r, POLL_MS));
|
|
89
|
+
if (spawnError)
|
|
90
|
+
return { ok: false, error: `Could not start ${plan.cmd}: ${spawnError.message}`, logPath };
|
|
91
|
+
if (exited !== null) {
|
|
92
|
+
return { ok: false, error: `The app exited (${exited}) before its CDP port answered. Last log lines:\n${tail(logPath)}`, logPath };
|
|
93
|
+
}
|
|
94
|
+
actual = devToolsPortFromLog(readLog(logPath)) ?? port;
|
|
95
|
+
devices = (await fetchDevices(actual)).filter(isChromiumTarget);
|
|
96
|
+
if (devices.length === 0)
|
|
97
|
+
continue;
|
|
98
|
+
firstSeen ??= Date.now();
|
|
99
|
+
if (devices.some(isUntitledPage) && Date.now() - firstSeen < TITLE_GRACE_MS)
|
|
100
|
+
continue;
|
|
101
|
+
return { ok: true, pid: child.pid, port: actual, logPath, devices };
|
|
102
|
+
}
|
|
103
|
+
if (devices.length > 0)
|
|
104
|
+
return { ok: true, pid: child.pid, port: actual, logPath, devices };
|
|
105
|
+
return {
|
|
106
|
+
ok: false,
|
|
107
|
+
error: `Port ${actual} listed no window within ${Math.round(timeoutMs / 1000)}s. The app is still running (pid ${child.pid}). ` +
|
|
108
|
+
`If its main process calls app.commandLine.appendSwitch('remote-debugging-port', ...), that port wins over this flag: ` +
|
|
109
|
+
`connect_metro({ port: <that port> }), or relaunch with that port. Last log lines:\n${tail(logPath)}`,
|
|
110
|
+
logPath,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=electronLaunch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"electronLaunch.js","sourceRoot":"","sources":["../../src/core/electronLaunch.ts"],"names":[],"mappings":"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"}
|
package/build/core/errors.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export declare class UserInputError extends Error {
|
|
|
3
3
|
readonly kind?: FailureKind;
|
|
4
4
|
constructor(message: string, context?: string, kind?: FailureKind);
|
|
5
5
|
}
|
|
6
|
-
export type FailureKind = "no_devices_attached" | "no_apps_connected" | "no_metro" | "driver_not_installed" | "no_debuggable_devices" | "devtools_hook_missing" | "no_metro_server" | "ws_closed" | "no_android_device" | "no_ios_simulator" | "no_fiber_roots" | "platform_mismatch" | "fiber_guard_unexpected" | "app_exception";
|
|
6
|
+
export type FailureKind = "no_devices_attached" | "no_apps_connected" | "no_metro" | "driver_not_installed" | "no_debuggable_devices" | "devtools_hook_missing" | "no_metro_server" | "ws_closed" | "no_android_device" | "no_ios_simulator" | "no_fiber_roots" | "platform_mismatch" | "fiber_guard_unexpected" | "app_exception" | "bad_arguments" | "js_dialog_open";
|
|
7
7
|
export declare const ENVIRONMENT_KINDS: ReadonlySet<FailureKind>;
|
|
8
8
|
export declare class EnvironmentError extends Error {
|
|
9
9
|
readonly kind: FailureKind;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAUA,qBAAa,cAAe,SAAQ,KAAK;IAMrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAU1B,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW;CAMpE;AAkBD,MAAM,MAAM,WAAW,GACjB,qBAAqB,GACrB,mBAAmB,GACnB,UAAU,GACV,sBAAsB,GACtB,uBAAuB,GACvB,uBAAuB,GACvB,iBAAiB,GACjB,WAAW,GACX,mBAAmB,GACnB,kBAAkB,GAClB,gBAAgB,GAChB,mBAAmB,GACnB,wBAAwB,GASxB,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAUA,qBAAa,cAAe,SAAQ,KAAK;IAMrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAU1B,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW;CAMpE;AAkBD,MAAM,MAAM,WAAW,GACjB,qBAAqB,GACrB,mBAAmB,GACnB,UAAU,GACV,sBAAsB,GACtB,uBAAuB,GACvB,uBAAuB,GACvB,iBAAiB,GACjB,WAAW,GACX,mBAAmB,GACnB,kBAAkB,GAClB,gBAAgB,GAChB,mBAAmB,GACnB,wBAAwB,GASxB,eAAe,GAef,eAAe,GAKf,gBAAgB,CAAC;AAQvB,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,WAAW,CAYrD,CAAC;AAOH,qBAAa,gBAAiB,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW;CAKjD"}
|
package/build/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,cAAe,SAAQ,KAAK;IAM5B,OAAO,CAAU;IAUjB,IAAI,CAAe;IAE5B,YAAY,OAAe,EAAE,OAAgB,EAAE,IAAkB;QAC7D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;CACJ;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,cAAe,SAAQ,KAAK;IAM5B,OAAO,CAAU;IAUjB,IAAI,CAAe;IAE5B,YAAY,OAAe,EAAE,OAAgB,EAAE,IAAkB;QAC7D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;CACJ;AAoED,MAAM,CAAC,MAAM,iBAAiB,GAA6B,IAAI,GAAG,CAAc;IAC5E,qBAAqB;IACrB,mBAAmB;IACnB,UAAU;IACV,sBAAsB;IACtB,uBAAuB;IACvB,uBAAuB;IACvB,iBAAiB;IACjB,WAAW;IACX,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;CACnB,CAAC,CAAC;AAOH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAC9B,IAAI,CAAc;IAE3B,YAAY,OAAe,EAAE,IAAiB;QAC1C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,KAAK;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,KAAK;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACnB;AAkpBD,eAAO,MAAM,mBAAmB,EAAE,MAItB,CAAC;AAEb,eAAO,MAAM,aAAa,EAAE,MAehB,CAAC;AAEb,wBAAgB,gBAAgB,IAAI,MAAM,CAWzC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI5D;AAED,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C"}
|
package/build/core/guides.js
CHANGED
|
@@ -13,7 +13,7 @@ const guides = [
|
|
|
13
13
|
- **Android:** ADB must be in PATH (comes with Android SDK Platform Tools)
|
|
14
14
|
|
|
15
15
|
## Quick Start
|
|
16
|
-
1. scan_metro — auto-discovers Metro on ports 8081-8090 and connects. Note: this occupies the CDP slot, which prevents the built-in React Native debugger from connecting. See "Switch to Native Debugger" below.
|
|
16
|
+
1. scan_metro — auto-discovers Metro on ports 8081-8090 and connects. Also probes Chromium/Electron debug ports: 9222 is listed but not auto-connected (attach with connect_metro({ port: 9222, device })), ports in EXECBRO_CHROMIUM_PORTS auto-connect. Note: this occupies the CDP slot, which prevents the built-in React Native debugger from connecting. See "Switch to Native Debugger" below.
|
|
17
17
|
2. get_apps — verify the app appears in connected list
|
|
18
18
|
3. get_connection_status — check connection health
|
|
19
19
|
|
|
@@ -41,8 +41,8 @@ exactly like "my fix didn't work".
|
|
|
41
41
|
- Use scan_metro to reconnect when done with native debugger
|
|
42
42
|
|
|
43
43
|
## Key Tools
|
|
44
|
-
- scan_metro: auto-discover and connect (preferred)
|
|
45
|
-
- connect_metro: connect to specific port (when you know it)
|
|
44
|
+
- scan_metro: auto-discover and connect React Native (Metro) and Chromium/Electron (CDP) targets (preferred)
|
|
45
|
+
- connect_metro: connect to a specific port (when you know it); device=<name> to attach one Chromium target
|
|
46
46
|
- disconnect_metro: close all connections (free CDP slot for native debugger)
|
|
47
47
|
- ensure_connection: health check with healthCheck=true
|
|
48
48
|
- get_connection_status: check uptime and gaps
|
|
@@ -162,7 +162,7 @@ size in a note when it applies.
|
|
|
162
162
|
{
|
|
163
163
|
id: "interact",
|
|
164
164
|
title: "Device Interaction",
|
|
165
|
-
summary: "Tap buttons, swipe, pinch to zoom, type text, and navigate the app UI",
|
|
165
|
+
summary: "Tap buttons, swipe, pinch to zoom, type text, answer browser dialogs, and navigate the app UI",
|
|
166
166
|
content: `# Device Interaction
|
|
167
167
|
|
|
168
168
|
## Prerequisites
|
|
@@ -255,7 +255,7 @@ tap detects TextInput elements (onChangeText/onFocus) in the fiber tree and fall
|
|
|
255
255
|
Inputs that already contain text are the most common verification-blocker. The typing tools APPEND by default — typing "https://app.example.com" into a field that already holds "https://demo.example.com" produces "https://demo.example.comhttps://app.example.com", not the intended replacement. Two tools handle this on Bridgeless/Fabric apps:
|
|
256
256
|
|
|
257
257
|
- **input_text with replace:true** — clear the focused field, then type, in a single call. This is the way to set a pre-filled field to an exact value. Works both by target (testID/component/textMatch) and, with native:true, on whatever already has focus.
|
|
258
|
-
- **dismiss_keyboard** — blur the currently focused TextInput, closing the on-screen keyboard. Useful before tapping buttons hidden behind the keyboard, or to verify "tap outside dismisses" behavior.
|
|
258
|
+
- **dismiss_keyboard** — blur the currently focused TextInput, closing the on-screen keyboard. Useful before tapping buttons hidden behind the keyboard, or to verify "tap outside dismisses" behavior. Nothing focused with the keyboard already down is reported as success, not an error — the caller asked for the keyboard down and it is down. Nothing focused with the keyboard UP is a real failure and says so: a native field owns it (system dialog, WebView, non-RN screen), so blurring React cannot close it — use android_key_event({key:"BACK"}) or tap outside the field on iOS.
|
|
259
259
|
|
|
260
260
|
dismiss_keyboard acts on whatever has focus; input_text focuses its own target unless native:true is passed. replace:true updates React state via onChangeText("") — controlled components (Formik, react-hook-form, useState) stay consistent. Calling publicInstance.clear() directly does NOT do this; it only updates the native side and leaves form state stale.
|
|
261
261
|
|
|
@@ -269,6 +269,8 @@ input_text reads the field back and compares. Several differences are the FIELD
|
|
|
269
269
|
- A value that gained formatting ("5551234567" -> "(555) 123-4567") is either a display mask (the write landed) or a field reinterpreting the number ("3700" -> "37.00", a different value). The text alone cannot tell these apart, so read the app's own state to decide.
|
|
270
270
|
- keyboardType: both write paths bypass the on-screen keyboard, so letters do reach a number-pad field. The write is allowed and noted — a test that passes only because the harness typed the untypeable is worth knowing about.
|
|
271
271
|
- An append onto a field whose prior text could not be read is verified by the TAIL that landed, not against a predicted whole value, and is never retried. The prediction starts from an empty field, so a correct append looked like a mismatch — and the retry clears first (the native path appends at the caret), which destroyed exactly the text the call was appending to.
|
|
272
|
+
- testID on a WRAPPER, not on the input itself, resolves — the custom <Input testID="x"> that keeps the id on its container and passes only value/onChangeText down is the ordinary RN shape. Accepted only when exactly one mounted input sits under it; a wrapper around several is refused rather than guessed between, and says which. When no input on the screen carries a testID of any kind, the error says that instead of echoing the id back — stop guessing ids and target by placeholder or label (textMatch=) or by index.
|
|
273
|
+
- Pure ASCII sent and another script back ("testing" -> "Еуіештп") is the simulator's ACTIVE keyboard layout reinterpreting US keycodes, and is named as such. Nothing is wrong with the field; switch the simulator to a Latin layout. Keystrokes only go through a layout when the React write path is unavailable (native:true, or no fiber tree reachable).
|
|
272
274
|
- native:true types into whatever the OS reports as FOCUSED, which a fiber tap on a TextInput does not necessarily move. The verdict names the field it wrote, so a mis-target reads as one instead of as a wrong value.
|
|
273
275
|
|
|
274
276
|
## Icon-Only Buttons
|
|
@@ -280,9 +282,11 @@ For buttons that contain only an icon (no text):
|
|
|
280
282
|
tap(text=...) skips fiber for non-ASCII (Hermes limitation) and uses accessibility/OCR instead. For best results, use testID or coordinates.
|
|
281
283
|
|
|
282
284
|
## Other Interactions
|
|
283
|
-
- swipe: cross-platform swipe/scroll. Easiest form: swipe({ direction: "up" }) scrolls to reveal more content (content-scroll semantics; "down"/"left"/"right" supported, bare swipe() defaults to "up"). Optional distance is in screenshot pixels (default 33% of the axis). For pixel-precise gestures pass all four startX/startY/endX/endY coordinates — they take precedence over direction. Use for FlatList/SectionList scrolling where off-screen items aren't mounted. Returns verification.meaningful — if false, warning names which no-op it was, by probing the scroll surface under the start point: already at top, already at end, content not scrollable, wrong axis, or no scroll view there at all. On a screen with no React Native connection it says it could not inspect the screen, rather than claiming the gesture missed — the gesture itself still went through, and swipe needs no RN connection to drive the device. Set burst:true to surface overscroll/bounce feedback even when the final state is unchanged. Set verify:false, screenshot:false for the fastest path. Pass delta on iOS to control touch step size.
|
|
285
|
+
- swipe: cross-platform swipe/scroll. Easiest form: swipe({ direction: "up" }) scrolls to reveal more content (content-scroll semantics; "down"/"left"/"right" supported, bare swipe() defaults to "up"). Optional distance is in screenshot pixels (default 33% of the axis). For pixel-precise gestures pass all four startX/startY/endX/endY coordinates — they take precedence over direction. Use for FlatList/SectionList scrolling where off-screen items aren't mounted. Returns verification.meaningful — if false, warning names which no-op it was, by probing the scroll surface under the start point: already at top, already at end, content not scrollable, wrong axis, or no scroll view there at all. On a screen with no React Native connection it says it could not inspect the screen, rather than claiming the gesture missed — the gesture itself still went through, and swipe needs no RN connection to drive the device. Set burst:true to surface overscroll/bounce feedback even when the final state is unchanged. Set verify:false, screenshot:false for the fastest path. Pass delta on iOS to control touch step size. On chromium a direction is one mouse-wheel event at the viewport centre (or startX/startY), verified by reading the scroll container's offsets (scrolled, container), and four coordinates are a left-button drag (sliders, resizable panes, pointer-event drag libraries; not native HTML5 draggable).
|
|
284
286
|
- input_text: type text — target with testID/component/textMatch (focuses itself), or pass native:true to type into whatever already has focus (system dialogs, non-RN screens). Pass replace:true to clear pre-filled values before typing (Bridgeless/Fabric only).
|
|
285
|
-
-
|
|
287
|
+
- press_key: keys that are not text: Enter to submit, Escape to close, Tab to move focus, arrows, Backspace, or a combo like Shift+Tab / Meta+K. Goes to the focused element, or pass testID/text to focus one first; repeat:N presses it N times. Works on chromium (CDP key events; the response names the focused element before and after), Android (adb keyevent, no modifier combos) and the iOS simulator (HID keys; combos need AXe).
|
|
288
|
+
- handle_dialog: accept or dismiss a JavaScript alert / confirm / prompt / beforeunload on a chromium page. A dialog pauses the page: tap, press_key, swipe and execute_in_app return it as dialog when they open one, and other page tools refuse until it is answered. Pass promptText for a prompt. Chromium only: an RN Alert is native UI, tap its button instead.
|
|
289
|
+
- dismiss_keyboard: blur the focused input, closing the keyboard. Already-down with nothing focused is a success; up with nothing focused means a native field owns it and only a platform dismiss will close it.
|
|
286
290
|
- ios_button / android_key_event: hardware buttons (HOME, BACK, etc.)
|
|
287
291
|
- ios_open_url: deep links and universal links
|
|
288
292
|
- get_images: retrieve screenshots already captured by any tool, including tap burst frames
|
|
@@ -299,6 +303,10 @@ router call through execute_in_app, which reports success whenever nothing throw
|
|
|
299
303
|
Do not know the route names? navigate({routeTable:true}) with NO destination just lists them —
|
|
300
304
|
call that first rather than guessing. A rejected destination also carries the registered routes
|
|
301
305
|
in its error, so a wrong guess still tells you the right answers.
|
|
306
|
+
An app written as a plain <NavigationContainer> with no ref prop is still reachable: the router is
|
|
307
|
+
resolved from a mounted screen's own navigation object, climbed to the root navigator. That route
|
|
308
|
+
has no getRootState, so the route table comes back empty and destination validation is skipped
|
|
309
|
+
rather than run against nothing — the note says when this happened.
|
|
302
310
|
|
|
303
311
|
## After Interactions
|
|
304
312
|
- Take a screenshot to verify the result`
|
|
@@ -624,11 +632,12 @@ export const UNTRUSTED_DATA_RULE = [
|
|
|
624
632
|
export const DECISION_TREE = [
|
|
625
633
|
"Primary tools: scan_metro, get_logs / search_logs, ios_screenshot / android_screenshot, tap, get_screen_state, get_screen_layout.",
|
|
626
634
|
"Platform-specific ios_* / android_* tools (ios_button, android_key_event, ios_open_url, etc.) are FALLBACKS for non-React or native-only flows — prefer the cross-platform primary tools above whenever possible. input_text covers native-only text entry too, via native:true.",
|
|
635
|
+
"Chromium/Electron targets (platform chromium) support logs, network capture and mocking, execute_in_app, globals, redux, component inspection, screen reading (get_screen_state, get_screen_layout, inspect_at_point, measure), screenshot, tap, input_text, swipe (wheel scroll, four-coordinate drag), press_key and handle_dialog (JavaScript alert / confirm / prompt); other tools refuse them with a message saying so. electron_launch_app starts an Electron project with the CDP port open.",
|
|
627
636
|
"",
|
|
628
637
|
"Call get_usage_guide(topic=...) for end-to-end workflows. Available topics:",
|
|
629
638
|
" setup — session setup (scan_metro, connect_metro, ensure_connection)",
|
|
630
639
|
" logs — console debugging (get_logs, search_logs)",
|
|
631
|
-
" interact — device interaction (tap, swipe, pinch, screenshots, input_text, dismiss_keyboard)",
|
|
640
|
+
" interact — device interaction (tap, swipe, pinch, screenshots, input_text, press_key, handle_dialog, dismiss_keyboard)",
|
|
632
641
|
" layout — on-screen layout check (get_screen_state, get_screen_layout)",
|
|
633
642
|
" inspect — component inspection (find_components, inspect_component, inspect_at_point)",
|
|
634
643
|
" network — network request inspection (get_network_requests, search_network)",
|
package/build/core/guides.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guides.js","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,GAAY;IACpB;QACI,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE,yDAAyD;QAClE,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qGA2CoF;KAChG;IACD;QACI,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,sBAAsB;QAC7B,OAAO,EAAE,mFAAmF;QAC5F,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4GAqC2F;KACvG;IACD;QACI,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,kBAAkB;QACzB,OAAO,EAAE,0EAA0E;QACnF,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0IA8DyH;KACrI;IACD;QACI,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"guides.js","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type AddressReader = () => string[];
|
|
2
|
+
export declare function rememberHostAddresses(): void;
|
|
3
|
+
export declare function hostAddressChangeHint(port?: number): string | null;
|
|
4
|
+
export declare function resetHostAddress(nextReader?: AddressReader): void;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=hostAddress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostAddress.d.ts","sourceRoot":"","sources":["../../src/core/hostAddress.ts"],"names":[],"mappings":"AAiBA,KAAK,aAAa,GAAG,MAAM,MAAM,EAAE,CAAC;AAYpC,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAGD,wBAAgB,qBAAqB,CAAC,IAAI,SAAO,GAAG,MAAM,GAAG,IAAI,CAchE;AAGD,wBAAgB,gBAAgB,CAAC,UAAU,GAAE,aAAgC,GAAG,IAAI,CAGnF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { networkInterfaces } from "os";
|
|
2
|
+
const readLanAddresses = () => Object.values(networkInterfaces())
|
|
3
|
+
.flat()
|
|
4
|
+
.filter(a => a && a.family === "IPv4" && !a.internal)
|
|
5
|
+
.map(a => a.address);
|
|
6
|
+
let reader = readLanAddresses;
|
|
7
|
+
let addressesAtConnect = null;
|
|
8
|
+
export function rememberHostAddresses() {
|
|
9
|
+
addressesAtConnect = reader();
|
|
10
|
+
}
|
|
11
|
+
export function hostAddressChangeHint(port = 8081) {
|
|
12
|
+
if (!addressesAtConnect)
|
|
13
|
+
return null;
|
|
14
|
+
const current = reader();
|
|
15
|
+
const lost = addressesAtConnect.filter(a => !current.includes(a));
|
|
16
|
+
if (lost.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
const url = encodeURIComponent(`http://localhost:${port}`);
|
|
19
|
+
return [
|
|
20
|
+
`NETWORK ADDRESS CHANGED: this machine was ${lost.join(", ")} when the app connected and is now ${current.join(", ") || "offline"}.`,
|
|
21
|
+
`The app is most likely still loading from the old address, so retrying scan_metro will not bring it back.`,
|
|
22
|
+
`Reload it from a reachable address, then scan_metro:`,
|
|
23
|
+
` iOS simulator (Expo dev client): xcrun simctl openurl booted "<app-scheme>://expo-development-client/?url=${url}" and accept the "Open in" prompt`,
|
|
24
|
+
` Android emulator: adb reverse tcp:${port} tcp:${port}, then relaunch the app`,
|
|
25
|
+
` Physical device: reopen the project from the dev launcher or a fresh QR code on the new address`,
|
|
26
|
+
].join("\n");
|
|
27
|
+
}
|
|
28
|
+
export function resetHostAddress(nextReader = readLanAddresses) {
|
|
29
|
+
reader = nextReader;
|
|
30
|
+
addressesAtConnect = null;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=hostAddress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostAddress.js","sourceRoot":"","sources":["../../src/core/hostAddress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;AAmBvC,MAAM,gBAAgB,GAAkB,GAAG,EAAE,CACzC,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;KAC7B,IAAI,EAAE;KACN,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;KACpD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC;AAE9B,IAAI,MAAM,GAAkB,gBAAgB,CAAC;AAC7C,IAAI,kBAAkB,GAAoB,IAAI,CAAC;AAG/C,MAAM,UAAU,qBAAqB;IACjC,kBAAkB,GAAG,MAAM,EAAE,CAAC;AAClC,CAAC;AAGD,MAAM,UAAU,qBAAqB,CAAC,IAAI,GAAG,IAAI;IAC7C,IAAI,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,GAAG,GAAG,kBAAkB,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO;QACH,6CAA6C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,sCAAsC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,GAAG;QACpI,2GAA2G;QAC3G,sDAAsD;QACtD,+GAA+G,GAAG,mCAAmC;QACrJ,uCAAuC,IAAI,QAAQ,IAAI,yBAAyB;QAChF,mGAAmG;KACtG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC;AAGD,MAAM,UAAU,gBAAgB,CAAC,aAA4B,gBAAgB;IACzE,MAAM,GAAG,UAAU,CAAC;IACpB,kBAAkB,GAAG,IAAI,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const FIBER_ROOTS_JS = "\nfunction __eb_fiberRoots(all) {\n var hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n var roots = [];\n var add = function (list) {\n for (var i = 0; i < list.length; i++) if (roots.indexOf(list[i]) < 0) roots.push(list[i]);\n };\n if (hook && typeof hook.getFiberRoots === 'function') {\n if (!all) {\n try { add(Array.from(hook.getFiberRoots(1) || [])); } catch (e) {}\n }\n if (roots.length === 0 && hook.renderers) {\n hook.renderers.forEach(function (_, id) {\n if (!all && roots.length > 0) return;\n try { add(Array.from(hook.getFiberRoots(id) || [])); } catch (e) {}\n });\n }\n }\n if (roots.length === 0 && typeof document !== 'undefined' && document) {\n var containerRoot = function (el) {\n if (!el) return null;\n var keys = Object.keys(el);\n for (var k = 0; k < keys.length; k++) {\n if (keys[k].indexOf('__reactContainer$') !== 0) continue;\n var f = el[keys[k]];\n return f ? (f.stateNode && f.stateNode.current ? f.stateNode : { current: f }) : null;\n }\n return null;\n };\n var seen = [];\n var scan = function (list) {\n for (var c = 0; c < list.length; c++) {\n if (!all && roots.length > 0) return;\n // #root is usually also one of body's children: read each element once.\n if (!list[c] || seen.indexOf(list[c]) >= 0) continue;\n seen.push(list[c]);\n var r = containerRoot(list[c]);\n if (r && roots.indexOf(r) < 0) roots.push(r);\n }\n };\n var candidates = [document.getElementById ? document.getElementById('root') : null];\n if (document.body) {\n candidates = candidates.concat(Array.from(document.body.children || []));\n candidates.push(document.body);\n }\n scan(candidates);\n // The usual spots missed: a container nested deeper (<div class=\"wrapper\"><div id=\"app\">).\n // ponytail: one Object.keys per element, only on a page where the fast path found nothing.\n if (roots.length === 0 && document.body && document.body.querySelectorAll) scan(Array.from(document.body.querySelectorAll('*')));\n }\n return roots;\n}\nfunction __eb_noRootsReason() {\n if (typeof document !== 'undefined' && document) return 'No fiber roots found on this page: it is not a React app, or React has not rendered yet.';\n return globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__\n ? 'No fiber roots found. The app may not have rendered yet.'\n : 'React DevTools hook not found. Make sure you are running a development build.';\n}\n";
|
|
2
|
+
//# sourceMappingURL=fiberRoots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fiberRoots.d.ts","sourceRoot":"","sources":["../../../src/core/injected/fiberRoots.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,cAAc,mwFA0D1B,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const FIBER_ROOTS_JS = `
|
|
2
|
+
function __eb_fiberRoots(all) {
|
|
3
|
+
var hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
4
|
+
var roots = [];
|
|
5
|
+
var add = function (list) {
|
|
6
|
+
for (var i = 0; i < list.length; i++) if (roots.indexOf(list[i]) < 0) roots.push(list[i]);
|
|
7
|
+
};
|
|
8
|
+
if (hook && typeof hook.getFiberRoots === 'function') {
|
|
9
|
+
if (!all) {
|
|
10
|
+
try { add(Array.from(hook.getFiberRoots(1) || [])); } catch (e) {}
|
|
11
|
+
}
|
|
12
|
+
if (roots.length === 0 && hook.renderers) {
|
|
13
|
+
hook.renderers.forEach(function (_, id) {
|
|
14
|
+
if (!all && roots.length > 0) return;
|
|
15
|
+
try { add(Array.from(hook.getFiberRoots(id) || [])); } catch (e) {}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (roots.length === 0 && typeof document !== 'undefined' && document) {
|
|
20
|
+
var containerRoot = function (el) {
|
|
21
|
+
if (!el) return null;
|
|
22
|
+
var keys = Object.keys(el);
|
|
23
|
+
for (var k = 0; k < keys.length; k++) {
|
|
24
|
+
if (keys[k].indexOf('__reactContainer$') !== 0) continue;
|
|
25
|
+
var f = el[keys[k]];
|
|
26
|
+
return f ? (f.stateNode && f.stateNode.current ? f.stateNode : { current: f }) : null;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
var seen = [];
|
|
31
|
+
var scan = function (list) {
|
|
32
|
+
for (var c = 0; c < list.length; c++) {
|
|
33
|
+
if (!all && roots.length > 0) return;
|
|
34
|
+
// #root is usually also one of body's children: read each element once.
|
|
35
|
+
if (!list[c] || seen.indexOf(list[c]) >= 0) continue;
|
|
36
|
+
seen.push(list[c]);
|
|
37
|
+
var r = containerRoot(list[c]);
|
|
38
|
+
if (r && roots.indexOf(r) < 0) roots.push(r);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var candidates = [document.getElementById ? document.getElementById('root') : null];
|
|
42
|
+
if (document.body) {
|
|
43
|
+
candidates = candidates.concat(Array.from(document.body.children || []));
|
|
44
|
+
candidates.push(document.body);
|
|
45
|
+
}
|
|
46
|
+
scan(candidates);
|
|
47
|
+
// The usual spots missed: a container nested deeper (<div class="wrapper"><div id="app">).
|
|
48
|
+
// ponytail: one Object.keys per element, only on a page where the fast path found nothing.
|
|
49
|
+
if (roots.length === 0 && document.body && document.body.querySelectorAll) scan(Array.from(document.body.querySelectorAll('*')));
|
|
50
|
+
}
|
|
51
|
+
return roots;
|
|
52
|
+
}
|
|
53
|
+
function __eb_noRootsReason() {
|
|
54
|
+
if (typeof document !== 'undefined' && document) return 'No fiber roots found on this page: it is not a React app, or React has not rendered yet.';
|
|
55
|
+
return globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__
|
|
56
|
+
? 'No fiber roots found. The app may not have rendered yet.'
|
|
57
|
+
: 'React DevTools hook not found. Make sure you are running a development build.';
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
//# sourceMappingURL=fiberRoots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fiberRoots.js","sourceRoot":"","sources":["../../../src/core/injected/fiberRoots.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0D7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputTarget.d.ts","sourceRoot":"","sources":["../../src/core/inputTarget.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,UAAU,GAAG;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,KAAK,CAAC,EAAE,MAAM,CAAC;IAYf,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;
|
|
1
|
+
{"version":3,"file":"inputTarget.d.ts","sourceRoot":"","sources":["../../src/core/inputTarget.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,UAAU,GAAG;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,KAAK,CAAC,EAAE,MAAM,CAAC;IAYf,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAKF,MAAM,MAAM,OAAO,GACb;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAEnC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvB,MAAM,MAAM,UAAU,GAAG;IACrB,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAQtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAO3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IASzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAK5B,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IAOb,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,SAAS,CAAC,EAAE,OAAO,CAAC;IASpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAO9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,YAAY,CAAC;AAicpD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,CAuF5E"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RN_PRIMITIVES_SRC, GENERIC_COMPONENT_SRC } from "./injectedFilters.js";
|
|
2
|
+
import { FIBER_ROOTS_JS } from "./injected/fiberRoots.js";
|
|
2
3
|
const HOST_INPUT_TYPES = `["RCTSinglelineTextInputView","RCTMultilineTextInputView","AndroidTextInput"]`;
|
|
3
4
|
const NO_FOCUS_REASON = "no focused TextInput. Pass testID (or component) so this tool can focus a field itself, " +
|
|
4
5
|
"or tap the field first. A tap reporting success does not guarantee React focus.";
|
|
@@ -8,15 +9,9 @@ function prelude(query) {
|
|
|
8
9
|
const wantText = query?.textMatch != null ? JSON.stringify(query.textMatch) : "null";
|
|
9
10
|
return `
|
|
10
11
|
var hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var rendererIds = Array.from(hook.renderers.keys());
|
|
15
|
-
for (var ri = 0; ri < rendererIds.length; ri++) {
|
|
16
|
-
var rs = Array.from(hook.getFiberRoots(rendererIds[ri]) || []);
|
|
17
|
-
for (var rj = 0; rj < rs.length; rj++) allRoots.push(rs[rj]);
|
|
18
|
-
}
|
|
19
|
-
if (allRoots.length === 0) return { found: false, reason: "no fiber roots" };
|
|
12
|
+
${FIBER_ROOTS_JS}
|
|
13
|
+
var allRoots = __eb_fiberRoots(true);
|
|
14
|
+
if (allRoots.length === 0) return hook ? { found: false, reason: "no fiber roots" } : { found: false, reason: "no devtools hook" };
|
|
20
15
|
|
|
21
16
|
var HOSTS = ${HOST_INPUT_TYPES};
|
|
22
17
|
var wantTestID = ${wantTestID};
|
|
@@ -230,6 +225,8 @@ function prelude(query) {
|
|
|
230
225
|
// right text written into the wrong field and still verifies clean — the
|
|
231
226
|
// exact class of confident-but-wrong result this tool exists to remove.
|
|
232
227
|
var __eb_matches = [];
|
|
228
|
+
// Inputs whose ancestor chain carries the wanted testID — a wrapper match.
|
|
229
|
+
var __eb_wrapHits = [];
|
|
233
230
|
var i;
|
|
234
231
|
|
|
235
232
|
// The pin, tried FIRST: the native tag of a field already resolved by an earlier op in the same call.
|
|
@@ -250,6 +247,29 @@ function prelude(query) {
|
|
|
250
247
|
for (i = 0; i < __eb_inputs.length; i++) {
|
|
251
248
|
if (__eb_testIDOf(__eb_inputs[i]) === wantTestID) __eb_matches.push(__eb_inputs[i]);
|
|
252
249
|
}
|
|
250
|
+
// The testID is on a WRAPPER, not on the TextInput itself. A custom
|
|
251
|
+
// <Input testID="login-password"> that puts its testID on the container
|
|
252
|
+
// View is the ordinary RN shape, and the deliberately narrow scope of
|
|
253
|
+
// __eb_testIDOf (host + controlling owner) cannot see it. Telemetry for
|
|
254
|
+
// the week to 2026-09-19: 10 of the 17 bad_target misses named a testID
|
|
255
|
+
// that plainly belonged to the screen in view (login-password,
|
|
256
|
+
// salary-input, local-payee-information-view-iban-input) while NOT ONE
|
|
257
|
+
// mounted input carried any testID at all.
|
|
258
|
+
//
|
|
259
|
+
// Accepted ONLY when exactly one input answers. That is what keeps the
|
|
260
|
+
// collision this scope was narrowed for: a ScrollView's shared ancestor
|
|
261
|
+
// id answers for every field beneath it, and an ambiguous match is no
|
|
262
|
+
// match. testID only, never nativeID, and never when the strict pass
|
|
263
|
+
// already found something.
|
|
264
|
+
if (__eb_matches.length === 0) {
|
|
265
|
+
for (i = 0; i < __eb_inputs.length; i++) {
|
|
266
|
+
for (var wa = __eb_inputs[i].return, wd = 0; wa && wd < 12; wa = wa.return, wd++) {
|
|
267
|
+
var wp = wa.memoizedProps;
|
|
268
|
+
if (wp && wp.testID === wantTestID) { __eb_wrapHits.push(__eb_inputs[i]); break; }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (__eb_wrapHits.length === 1) __eb_matches.push(__eb_wrapHits[0]);
|
|
272
|
+
}
|
|
253
273
|
} else if (wantComponent !== null) {
|
|
254
274
|
var wc = String(wantComponent).toLowerCase();
|
|
255
275
|
for (i = 0; i < __eb_inputs.length; i++) {
|
|
@@ -306,14 +326,33 @@ function prelude(query) {
|
|
|
306
326
|
// C3, and error-message quality ONLY: no matcher is loosened, nothing is guessed, the miss is still a miss. Verified live 2026-08-22 — testID "name-inpu" against a mounted "name-input" returned the bare "no TextInput matched that target" plus the candidate list, and the list pushes everything useful past the 200-char truncation telemetry applies to the message, so the closest match goes at the FRONT of the string.
|
|
307
327
|
//
|
|
308
328
|
// Telemetry 2026-08-22: 26 of the 145 bad_target failures in 7 days are strict-equality testID misses (login.username.input, search-input, church-search-list-search-input) — names that plainly belong to the screen the caller was looking at, off by a prefix. Containment either way catches those for one lowercase compare per mounted input, which is what this can afford: it runs inside the user's app on every failed call.
|
|
309
|
-
if (
|
|
329
|
+
if (__eb_wrapHits.length > 1) {
|
|
330
|
+
// A wrapper DID carry the id, but it wraps more than one field, so
|
|
331
|
+
// resolving it would be a guess between them.
|
|
332
|
+
reason = 'testID "' + wantTestID + '" is on a wrapper around ' + __eb_wrapHits.length +
|
|
333
|
+
' of the ' + __eb_inputs.length + ' mounted input(s), not on any one of them — target the field itself by placeholder or label (textMatch=), or pass index';
|
|
334
|
+
} else if (wantTestID !== null) {
|
|
310
335
|
var wid = String(wantTestID).toLowerCase();
|
|
336
|
+
var anyTestID = false;
|
|
311
337
|
for (var h = 0; h < candidates.length; h++) {
|
|
312
338
|
var cid = candidates[h].testID ? String(candidates[h].testID).toLowerCase() : "";
|
|
313
339
|
if (cid && (cid.indexOf(wid) !== -1 || wid.indexOf(cid) !== -1)) {
|
|
314
340
|
reason = 'did you mean testID "' + candidates[h].testID + '" (index ' + candidates[h].index + ')? no mounted input has testID "' + wantTestID + '" (' + __eb_inputs.length + " input(s) mounted)";
|
|
341
|
+
anyTestID = true;
|
|
315
342
|
break;
|
|
316
343
|
}
|
|
344
|
+
if (cid) anyTestID = true;
|
|
345
|
+
}
|
|
346
|
+
// Not one mounted input carries a testID of any kind, and no wrapper
|
|
347
|
+
// above them does either. Repeating the target back is then the least
|
|
348
|
+
// useful thing to say: the caller is guessing at ids this screen simply
|
|
349
|
+
// does not have, and the answer is to stop guessing and describe the
|
|
350
|
+
// field. Six of the eight installs that hit this cluster retried the
|
|
351
|
+
// same invented id at least once.
|
|
352
|
+
if (!anyTestID) {
|
|
353
|
+
reason = 'no input on this screen has a testID (' + __eb_inputs.length +
|
|
354
|
+
' mounted, none with one, and no wrapper carries "' + wantTestID +
|
|
355
|
+
'" either) — target by placeholder or label instead (textMatch=), or by index, using the list below';
|
|
317
356
|
}
|
|
318
357
|
}
|
|
319
358
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputTarget.js","sourceRoot":"","sources":["../../src/core/inputTarget.ts"],"names":[],"mappings":"AAgDA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"inputTarget.js","sourceRoot":"","sources":["../../src/core/inputTarget.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAWnF,wBAAsB,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgCzE;AAmBD,wBAAsB,cAAc,CAChC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,GAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAC/B,GACP,OAAO,CAAC,eAAe,CAAC,CAib1B;AAOD,wBAAsB,oBAAoB,CACtC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAc9B;AAMD,wBAAsB,gBAAgB,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,iBAAiB,EAAE,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAUlC"}
|
package/build/core/inspector.js
CHANGED
|
@@ -3,19 +3,15 @@ import { resolveStacksToSource, buildDebugStackHarvestExpression } from "./compo
|
|
|
3
3
|
import { RN_PRIMITIVES_SRC, GENERIC_COMPONENT_SRC } from "./injectedFilters.js";
|
|
4
4
|
import { SCREEN_SPACE_HELPER_JS } from "./screenSpace.js";
|
|
5
5
|
import { SHEET_HELPERS_JS } from "./injected/sheetOffset.js";
|
|
6
|
+
import { FIBER_ROOTS_JS } from "./injected/fiberRoots.js";
|
|
6
7
|
export async function isInspectorActive(device) {
|
|
7
8
|
const expression = `
|
|
8
9
|
(function() {
|
|
9
10
|
const hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
10
11
|
if (!hook) return false;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
for (const [id] of (hook.renderers || [])) {
|
|
15
|
-
roots = [...(hook.getFiberRoots?.(id) || [])];
|
|
16
|
-
if (roots.length > 0) break;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
13
|
+
${FIBER_ROOTS_JS}
|
|
14
|
+
const roots = __eb_fiberRoots(false);
|
|
19
15
|
if (roots.length === 0) return false;
|
|
20
16
|
|
|
21
17
|
function findComponent(fiber, targetName, depth = 0) {
|
|
@@ -46,21 +42,9 @@ export async function inspectAtPoint(x, y, options = {}) {
|
|
|
46
42
|
const expression = `
|
|
47
43
|
new Promise(function(resolve) {
|
|
48
44
|
var hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (hook.getFiberRoots) {
|
|
53
|
-
try { roots = Array.from(hook.getFiberRoots(1) || []); } catch(e) {}
|
|
54
|
-
}
|
|
55
|
-
if (roots.length === 0 && hook.renderers) {
|
|
56
|
-
for (var entry of hook.renderers) {
|
|
57
|
-
try {
|
|
58
|
-
var r = Array.from(hook.getFiberRoots ? (hook.getFiberRoots(entry[0]) || []) : []);
|
|
59
|
-
if (r.length > 0) { roots = r; break; }
|
|
60
|
-
} catch(e) {}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (roots.length === 0) return resolve({ error: 'No fiber roots found. The app may not have rendered yet.' });
|
|
45
|
+
${FIBER_ROOTS_JS}
|
|
46
|
+
var roots = __eb_fiberRoots(false);
|
|
47
|
+
if (roots.length === 0) return resolve({ error: __eb_noRootsReason() });
|
|
64
48
|
|
|
65
49
|
// Paper: measureInWindow is on stateNode directly.
|
|
66
50
|
// Fabric: measureInWindow is on stateNode.canonical.publicInstance.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;AAE/F,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAA2B,MAAM,kBAAkB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"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"}
|
package/build/core/ios.d.ts
CHANGED
|
@@ -74,6 +74,18 @@ export declare function iosKeyEvent(keycode: number, options?: {
|
|
|
74
74
|
duration?: number;
|
|
75
75
|
udid?: string;
|
|
76
76
|
}): Promise<iOSResult>;
|
|
77
|
+
export declare function hidKeyFor(combo: {
|
|
78
|
+
mods: number;
|
|
79
|
+
key: {
|
|
80
|
+
key: string;
|
|
81
|
+
};
|
|
82
|
+
}): {
|
|
83
|
+
keycode: number;
|
|
84
|
+
modifiers: number[];
|
|
85
|
+
} | {
|
|
86
|
+
error: string;
|
|
87
|
+
};
|
|
88
|
+
export declare function iosKeyCombo(modifiers: number[], keycode: number, udid?: string): Promise<iOSResult>;
|
|
77
89
|
export declare function iosKeySequence(keycodes: number[], udid?: string): Promise<iOSResult>;
|
|
78
90
|
export declare function getIOSSafeAreaTop(udid?: string): Promise<number>;
|
|
79
91
|
export declare function getIOSScreenPointSize(udid?: string): Promise<{
|