peachsim 0.1.1620 → 0.1.1625
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 +35 -5
- package/cli/app-fonts.ts +2 -1
- package/cli/bridge-flow-runner.ts +184 -113
- package/cli/cloud-client.ts +68 -57
- package/cli/commands/box/search-command.ts +3 -2
- package/cli/commands/box.ts +10 -29
- package/cli/commands/control.ts +108 -43
- package/cli/commands/inspect/settling.ts +57 -20
- package/cli/commands/maestro-compare.ts +11 -32
- package/cli/commands/platform.ts +71 -36
- package/cli/commands/upload.ts +5 -1
- package/cli/dev-build-freshness.ts +37 -2
- package/cli/drivers/playwright-sim-host.ts +6 -5
- package/cli/maestro-accessibility.ts +53 -0
- package/cli/maestro-compare.ts +24 -0
- package/cli/outbound-endpoints.ts +22 -5
- package/cli/parent-pid.ts +0 -9
- package/cli/remote-simulators.ts +112 -0
- package/cli/remoteSimulatorContract.ts +21 -0
- package/detox/expectations.ts +5 -1
- package/detox/index.ts +133 -98
- package/detox/motion-change.cjs +37 -0
- package/detox/motion-change.d.cts +16 -0
- package/detox/navigation-lifecycle.ts +22 -4
- package/dist-lib/agent-daemon-client.cjs +3 -2
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +3 -2
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/bundle-channel.cjs +1520 -934
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +3 -2
- package/dist-lib/cloud.mjs +3 -2
- package/dist-lib/config.cjs +5 -4
- package/dist-lib/config.mjs +5 -4
- package/dist-lib/detox/index.cjs +1021 -364
- package/dist-lib/dev-bundle-resolution.cjs +51 -23
- package/dist-lib/expo-swift-bundle.cjs +1343 -801
- package/dist-lib/expo-swift-metadata.cjs +5 -4
- package/dist-lib/expo-swift-metadata.mjs +5 -4
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +2468 -1341
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1262 -300
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +1 -1
- package/dist-lib/menu.cjs +3 -2
- package/dist-lib/menu.mjs +3 -2
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +5 -4
- package/dist-lib/metro-production-bundle.mjs +5 -4
- package/dist-lib/metro.cjs +799 -398
- package/dist-lib/native-app-identity-project.cjs +728 -22
- package/dist-lib/native-app-identity-project.mjs +727 -22
- package/dist-lib/native-app-identity.cjs +224 -9
- package/dist-lib/native-app-identity.mjs +222 -8
- package/dist-lib/native-firebase-metadata.cjs +5 -4
- package/dist-lib/native-firebase-metadata.mjs +5 -4
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +3 -2
- package/dist-lib/react-native-host-modules.cjs +4 -1
- package/dist-lib/react-native-host-modules.mjs +4 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +94 -28
- package/dist-lib/sdk.cjs +89 -24
- package/dist-lib/sdk.mjs +89 -24
- package/dist-lib/skills.cjs +4391 -2350
- package/dist-lib/swift-compile.cjs +328 -142
- package/dist-lib/swift-compile.mjs +342 -147
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +888 -559
- package/dist-lib/vite.cjs +68 -14
- package/dist-lib/worklet-executable.cjs +25 -2
- package/dist-lib/worklet-executable.mjs +25 -2
- package/package.json +2 -2
- package/scripts/dev-server-scanner.ts +33 -13
- package/src/admitted-mac-build.ts +34 -8
- package/src/android-app-identity.ts +146 -0
- package/src/android-autolinking.ts +75 -0
- package/src/android-string-value.ts +36 -0
- package/src/android-strings.ts +5 -36
- package/src/androidAutolinkingContract.ts +40 -0
- package/src/bundleGlobalFooter.ts +26 -7
- package/src/codex-client.ts +3 -2
- package/src/dev-bundle-resolution.ts +58 -25
- package/src/expo-kotlin-host.ts +6 -36
- package/src/expo-swift-bundle.ts +17 -12
- package/src/expo-swift-host.ts +477 -173
- package/src/expoSwiftContract.ts +6 -0
- package/src/host/bridge-host.ts +7 -55
- package/src/host/staged-host-files.ts +29 -2
- package/src/installed-package-versions.ts +54 -14
- package/src/launchMetadataContract.ts +24 -0
- package/src/metro-plugin.ts +37 -42
- package/src/native-app-identity-project.ts +116 -3
- package/src/native-app-identity.ts +86 -11
- package/src/nitro-compile.ts +2 -5
- package/src/nitro-source.ts +147 -63
- package/src/process-group.ts +90 -60
- package/src/process-output.ts +0 -9
- package/src/public-brand.ts +1 -0
- package/src/react-native-host-modules.ts +3 -0
- package/src/sim-client.ts +6 -4
- package/src/swift-compile.ts +176 -28
- package/src/swift-distribution.lock.json +37 -11
- package/src/swift-distribution.ts +61 -9
- package/src/swift-host.ts +58 -27
- package/src/swift-objc-standin.ts +13 -0
- package/src/swift-standin-emit.ts +1 -1
- package/src/swift-standins.ts +17 -5
- package/src/vite-plugin.ts +8 -19
- package/src/worklet-executable.ts +30 -3
- package/src/worklets-babel.ts +35 -14
- package/src/xcode-project.ts +10 -0
package/dist-lib/detox/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1216,6 +1216,22 @@ var require_motion_change = __commonJS({
|
|
|
1216
1216
|
definition: MOTION_CHANGE_DEFINITION2
|
|
1217
1217
|
});
|
|
1218
1218
|
}
|
|
1219
|
+
var DENSE_SAMPLE_MAX_GAP_MS = 1e3 / 60 + 1;
|
|
1220
|
+
var DENSE_SAMPLE_MINIMUM_MOVING_PAIRS = 6;
|
|
1221
|
+
function evaluateMotionTransitions(transitions) {
|
|
1222
|
+
const measured = transitions.every(
|
|
1223
|
+
(transition) => transition.dimensionsMatch && transition.changePercent !== null && transition.changePixels !== null && transition.totalPixels !== null
|
|
1224
|
+
);
|
|
1225
|
+
const moving = transitions.filter((transition) => transition.passedMinimum).length;
|
|
1226
|
+
const dense = transitions.length > DENSE_SAMPLE_MINIMUM_MOVING_PAIRS && transitions.every(
|
|
1227
|
+
(transition) => transition.toOffsetMs - transition.fromOffsetMs <= DENSE_SAMPLE_MAX_GAP_MS
|
|
1228
|
+
);
|
|
1229
|
+
return {
|
|
1230
|
+
dense,
|
|
1231
|
+
moving,
|
|
1232
|
+
passed: transitions.length > 0 && measured && (dense ? moving >= DENSE_SAMPLE_MINIMUM_MOVING_PAIRS : moving === transitions.length)
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1219
1235
|
var DISPLAY_LINK_INTERVAL_MS = 1e3 / 60;
|
|
1220
1236
|
var DISCRETE_FRAME_TIMING_TOLERANCE_MS = 1e3 / 60 + 1e3 / 600;
|
|
1221
1237
|
function parseDiscreteFrameCadence(value) {
|
|
@@ -1371,6 +1387,7 @@ var require_motion_change = __commonJS({
|
|
|
1371
1387
|
MOTION_CHANGE_DEFINITION: MOTION_CHANGE_DEFINITION2,
|
|
1372
1388
|
measureMotionChange: measureMotionChange2,
|
|
1373
1389
|
measureProofMotionChange,
|
|
1390
|
+
evaluateMotionTransitions,
|
|
1374
1391
|
DISCRETE_FRAME_TIMING_TOLERANCE_MS,
|
|
1375
1392
|
parseDiscreteFrameCadence,
|
|
1376
1393
|
classifyDiscreteFrame: classifyDiscreteFrame2,
|
|
@@ -1398,23 +1415,23 @@ function previousRemoteBuildDelivery(destination) {
|
|
|
1398
1415
|
if (!label) return void 0;
|
|
1399
1416
|
const local = newestCompletedDelivery(root, label, (0, import_node_path2.basename)(destination));
|
|
1400
1417
|
if (local) return local;
|
|
1401
|
-
const commonDir = (0,
|
|
1418
|
+
const commonDir = (0, import_node_child_process3.spawnSync)(
|
|
1402
1419
|
"git",
|
|
1403
1420
|
["rev-parse", "--path-format=absolute", "--git-common-dir"],
|
|
1404
1421
|
{ cwd: (0, import_node_path2.dirname)(root), encoding: "utf8" }
|
|
1405
1422
|
);
|
|
1406
1423
|
if (commonDir.status !== 0) return void 0;
|
|
1407
1424
|
const primary = (0, import_node_path2.join)((0, import_node_path2.dirname)(commonDir.stdout.trim()), ".remote-deliveries");
|
|
1408
|
-
if (primary === root || !(0,
|
|
1425
|
+
if (primary === root || !(0, import_node_fs3.existsSync)(primary)) return void 0;
|
|
1409
1426
|
return newestCompletedDelivery(primary, label);
|
|
1410
1427
|
}
|
|
1411
1428
|
function deliveryGroup(name2) {
|
|
1412
1429
|
return /^([a-z0-9-]+)-[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/.exec(name2)?.[1] ?? (/^\d+-\d+$/.test(name2) ? "default" : void 0);
|
|
1413
1430
|
}
|
|
1414
1431
|
function newestCompletedDelivery(root, label, exclude) {
|
|
1415
|
-
return (0,
|
|
1432
|
+
return (0, import_node_fs3.readdirSync)(root, { withFileTypes: true }).filter(
|
|
1416
1433
|
(entry) => entry.isDirectory() && entry.name !== exclude && deliveryGroup(entry.name) === label
|
|
1417
|
-
).map((entry) => (0, import_node_path2.join)(root, entry.name)).filter((path3) => (0,
|
|
1434
|
+
).map((entry) => (0, import_node_path2.join)(root, entry.name)).filter((path3) => (0, import_node_fs3.existsSync)((0, import_node_path2.join)(path3, ".remote-transfer-complete"))).map((path3) => ({ path: path3, modified: (0, import_node_fs3.statSync)(path3).mtimeMs })).sort((left, right) => right.modified - left.modified)[0]?.path;
|
|
1418
1435
|
}
|
|
1419
1436
|
function prunePreviousRemoteBuildDeliveries(destination, keepCount = 1) {
|
|
1420
1437
|
const root = (0, import_node_path2.dirname)((0, import_node_path2.resolve)(destination));
|
|
@@ -1422,15 +1439,15 @@ function prunePreviousRemoteBuildDeliveries(destination, keepCount = 1) {
|
|
|
1422
1439
|
const label = deliveryGroup((0, import_node_path2.basename)(destination));
|
|
1423
1440
|
if (!label) return;
|
|
1424
1441
|
const destinationPath = (0, import_node_path2.resolve)(destination);
|
|
1425
|
-
const entries = (0,
|
|
1426
|
-
const completed = entries.filter((path3) => (0,
|
|
1442
|
+
const entries = (0, import_node_fs3.readdirSync)(root, { withFileTypes: true }).filter((entry) => entry.isDirectory() && deliveryGroup(entry.name) === label).map((entry) => (0, import_node_path2.join)(root, entry.name));
|
|
1443
|
+
const completed = entries.filter((path3) => (0, import_node_fs3.existsSync)((0, import_node_path2.join)(path3, ".remote-transfer-complete"))).map((path3) => ({ path: path3, modified: (0, import_node_fs3.statSync)(path3).mtimeMs })).sort((left, right) => right.modified - left.modified);
|
|
1427
1444
|
const toKeep = /* @__PURE__ */ new Set([destinationPath]);
|
|
1428
1445
|
for (let index = 0; index < keepCount && index < completed.length; index++) {
|
|
1429
1446
|
toKeep.add(completed[index].path);
|
|
1430
1447
|
}
|
|
1431
1448
|
for (const entry of completed) {
|
|
1432
1449
|
if (!toKeep.has(entry.path)) {
|
|
1433
|
-
(0,
|
|
1450
|
+
(0, import_node_fs3.rmSync)(entry.path, { recursive: true, force: true });
|
|
1434
1451
|
}
|
|
1435
1452
|
}
|
|
1436
1453
|
}
|
|
@@ -1443,13 +1460,13 @@ function remoteBuildReportPath(args, leg, relativeReport) {
|
|
|
1443
1460
|
}
|
|
1444
1461
|
return (0, import_node_path2.join)((0, import_node_path2.resolve)(directory), relativeReport);
|
|
1445
1462
|
}
|
|
1446
|
-
var
|
|
1463
|
+
var import_node_child_process3, import_node_crypto2, import_node_fs3, import_node_path2;
|
|
1447
1464
|
var init_remote_build_delivery = __esm({
|
|
1448
1465
|
"../../scripts/lib/remote-build-delivery.ts"() {
|
|
1449
1466
|
"use strict";
|
|
1450
|
-
|
|
1467
|
+
import_node_child_process3 = require("node:child_process");
|
|
1451
1468
|
import_node_crypto2 = require("node:crypto");
|
|
1452
|
-
|
|
1469
|
+
import_node_fs3 = require("node:fs");
|
|
1453
1470
|
import_node_path2 = require("node:path");
|
|
1454
1471
|
}
|
|
1455
1472
|
});
|
|
@@ -1567,10 +1584,10 @@ var require_native_frame_receipt = __commonJS({
|
|
|
1567
1584
|
decodeNativeFramebuffer,
|
|
1568
1585
|
writeNativeFramebufferPng
|
|
1569
1586
|
};
|
|
1570
|
-
async function buildNativeFrameConsumer({ root, cacheRoot }) {
|
|
1587
|
+
async function buildNativeFrameConsumer({ root, cacheRoot, waitForAdmission = false }) {
|
|
1571
1588
|
const fs3 = require("node:fs");
|
|
1572
1589
|
const path3 = require("node:path");
|
|
1573
|
-
const { spawn } = require("node:child_process");
|
|
1590
|
+
const { spawn: spawn2 } = require("node:child_process");
|
|
1574
1591
|
const source = path3.join(root, "scripts/debug/native-ios-frame-consumer.m");
|
|
1575
1592
|
const sourceSha256 = createHash("sha256").update(fs3.readFileSync(source)).digest("hex");
|
|
1576
1593
|
const cache = path3.join(cacheRoot, "frame-consumer", sourceSha256);
|
|
@@ -1579,13 +1596,14 @@ var require_native_frame_receipt = __commonJS({
|
|
|
1579
1596
|
const { remoteBuildDelivery: remoteBuildDelivery2 } = await Promise.resolve().then(() => (init_remote_build_delivery(), remote_build_delivery_exports));
|
|
1580
1597
|
const delivery = remoteBuildDelivery2(root, "native-frame-consumer");
|
|
1581
1598
|
await new Promise((resolve3, reject) => {
|
|
1582
|
-
const child =
|
|
1599
|
+
const child = spawn2(
|
|
1583
1600
|
"bun",
|
|
1584
1601
|
[
|
|
1585
1602
|
"remote",
|
|
1586
1603
|
"--delivery-dir",
|
|
1587
1604
|
delivery,
|
|
1588
1605
|
"--mac",
|
|
1606
|
+
...waitForAdmission ? ["--wait"] : [],
|
|
1589
1607
|
"bash",
|
|
1590
1608
|
"-c",
|
|
1591
1609
|
'actual=$(shasum -a 256 scripts/debug/native-ios-frame-consumer.m); test "${actual%% *}" = "$1" && mkdir -p .remote-out && clang -fobjc-arc -framework Foundation -framework IOSurface -lcompression scripts/debug/native-ios-frame-consumer.m -o .remote-out/native-frame-consumer && printf "%s\\n" "$1" > .remote-out/native-frame-consumer.source-sha256',
|
|
@@ -1685,7 +1703,7 @@ var require_native_frame_receipt = __commonJS({
|
|
|
1685
1703
|
async function encodeNativeFramebufferMovie(rawDir, videoPath) {
|
|
1686
1704
|
const fs3 = require("node:fs");
|
|
1687
1705
|
const path3 = require("node:path");
|
|
1688
|
-
const { spawn } = require("node:child_process");
|
|
1706
|
+
const { spawn: spawn2 } = require("node:child_process");
|
|
1689
1707
|
const { Readable } = require("node:stream");
|
|
1690
1708
|
const { pipeline } = require("node:stream/promises");
|
|
1691
1709
|
const rows = fs3.readFileSync(path3.join(rawDir, "frames.jsonl"), "utf8").split("\n").filter(Boolean).map((line) => JSON.parse(line));
|
|
@@ -1725,7 +1743,7 @@ var require_native_frame_receipt = __commonJS({
|
|
|
1725
1743
|
let activeProcess;
|
|
1726
1744
|
let deadline;
|
|
1727
1745
|
try {
|
|
1728
|
-
encoder =
|
|
1746
|
+
encoder = spawn2(
|
|
1729
1747
|
"ffmpeg",
|
|
1730
1748
|
[
|
|
1731
1749
|
"-v",
|
|
@@ -1801,7 +1819,7 @@ var require_native_frame_receipt = __commonJS({
|
|
|
1801
1819
|
completed
|
|
1802
1820
|
]);
|
|
1803
1821
|
const media = await new Promise((resolve3, reject) => {
|
|
1804
|
-
const probe =
|
|
1822
|
+
const probe = spawn2(
|
|
1805
1823
|
"ffprobe",
|
|
1806
1824
|
[
|
|
1807
1825
|
"-v",
|
|
@@ -1887,7 +1905,7 @@ var require_attempt_events = __commonJS({
|
|
|
1887
1905
|
}
|
|
1888
1906
|
module2.exports = { attemptEventsPath, writeAttemptEvent: writeAttemptEvent2 };
|
|
1889
1907
|
var crypto2 = require("node:crypto");
|
|
1890
|
-
var { spawnSync:
|
|
1908
|
+
var { spawnSync: spawnSync3 } = require("node:child_process");
|
|
1891
1909
|
var {
|
|
1892
1910
|
parseDiscreteFrameCadence,
|
|
1893
1911
|
classifyDiscreteFrame: classifyDiscreteFrame2,
|
|
@@ -2011,7 +2029,7 @@ var require_attempt_events = __commonJS({
|
|
|
2011
2029
|
return context;
|
|
2012
2030
|
}
|
|
2013
2031
|
function decodeDiscreteNativeFrames(recording, cadence, probeRect, rootRect) {
|
|
2014
|
-
const metadata =
|
|
2032
|
+
const metadata = spawnSync3(
|
|
2015
2033
|
"ffprobe",
|
|
2016
2034
|
[
|
|
2017
2035
|
"-v",
|
|
@@ -2040,7 +2058,7 @@ var require_attempt_events = __commonJS({
|
|
|
2040
2058
|
const width = Math.round(probeRect.width * sx), height = Math.round(probeRect.height * sy);
|
|
2041
2059
|
if (x < 0 || y < 0 || width <= 0 || height <= 0 || x + width > stream.width || y + height > stream.height)
|
|
2042
2060
|
throw new Error("cadence recording probe escapes its original frame");
|
|
2043
|
-
const decoded =
|
|
2061
|
+
const decoded = spawnSync3(
|
|
2044
2062
|
"ffmpeg",
|
|
2045
2063
|
[
|
|
2046
2064
|
"-v",
|
|
@@ -2581,7 +2599,7 @@ __export(detox_exports, {
|
|
|
2581
2599
|
module.exports = __toCommonJS(detox_exports);
|
|
2582
2600
|
var import_crypto = require("crypto");
|
|
2583
2601
|
var fs2 = __toESM(require("fs"), 1);
|
|
2584
|
-
var
|
|
2602
|
+
var import_node_child_process4 = require("node:child_process");
|
|
2585
2603
|
var import_node_module = require("node:module");
|
|
2586
2604
|
var import_node_util = require("node:util");
|
|
2587
2605
|
var path2 = __toESM(require("path"), 1);
|
|
@@ -2589,11 +2607,60 @@ var import_playwright_core = require("playwright-core");
|
|
|
2589
2607
|
|
|
2590
2608
|
// ../../scripts/lib/reap-browser.ts
|
|
2591
2609
|
var childProcess = __toESM(require("node:child_process"), 1);
|
|
2592
|
-
var
|
|
2610
|
+
var import_node_child_process2 = require("node:child_process");
|
|
2593
2611
|
var fs = __toESM(require("node:fs"), 1);
|
|
2594
2612
|
var os = __toESM(require("node:os"), 1);
|
|
2595
2613
|
var path = __toESM(require("node:path"), 1);
|
|
2596
2614
|
|
|
2615
|
+
// src/process-group.ts
|
|
2616
|
+
var import_node_child_process = require("node:child_process");
|
|
2617
|
+
var import_node_fs = require("node:fs");
|
|
2618
|
+
function listProcessChildren(parents, timeoutMs = 3e3) {
|
|
2619
|
+
if (parents.some((pid) => !Number.isInteger(pid) || pid <= 1))
|
|
2620
|
+
throw new Error("process inspection requires valid parent pids");
|
|
2621
|
+
if (parents.length === 0) return [];
|
|
2622
|
+
const deadline = Date.now() + timeoutMs;
|
|
2623
|
+
let children;
|
|
2624
|
+
if (process.platform === "linux") {
|
|
2625
|
+
const lists = [];
|
|
2626
|
+
for (const parent of parents) {
|
|
2627
|
+
try {
|
|
2628
|
+
const tasks = `/proc/${parent}/task`;
|
|
2629
|
+
for (const thread of (0, import_node_fs.readdirSync)(tasks)) {
|
|
2630
|
+
if (Date.now() >= deadline)
|
|
2631
|
+
throw new Error("process descendant inspection exceeded its deadline");
|
|
2632
|
+
try {
|
|
2633
|
+
lists.push((0, import_node_fs.readFileSync)(`${tasks}/${thread}/children`, "utf8"));
|
|
2634
|
+
} catch (error) {
|
|
2635
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
|
|
2636
|
+
throw error;
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
} catch (error) {
|
|
2640
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
|
|
2641
|
+
throw error;
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
children = lists.join(" ");
|
|
2645
|
+
} else {
|
|
2646
|
+
const result = (0, import_node_child_process.spawnSync)("pgrep", ["-P", parents.join(",")], {
|
|
2647
|
+
encoding: "utf8",
|
|
2648
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2649
|
+
timeout: Math.max(1, timeoutMs),
|
|
2650
|
+
killSignal: "SIGKILL"
|
|
2651
|
+
});
|
|
2652
|
+
if (result.error || result.status !== 0 && result.status !== 1) {
|
|
2653
|
+
throw new Error(
|
|
2654
|
+
`could not inspect descendants of processes ${parents.join(",")}: ${result.error?.message || result.stderr.trim() || `pgrep exited ${result.status}`}`
|
|
2655
|
+
);
|
|
2656
|
+
}
|
|
2657
|
+
children = result.stdout;
|
|
2658
|
+
}
|
|
2659
|
+
return [...new Set(children.trim().split(/\s+/).map(Number))].filter(
|
|
2660
|
+
(pid) => Number.isInteger(pid) && pid > 1 && !parents.includes(pid)
|
|
2661
|
+
);
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2597
2664
|
// ../../scripts/lib/chromium-admission.ts
|
|
2598
2665
|
function readChromiumQueue(deps, verified, own) {
|
|
2599
2666
|
const { fs: fs3, os: os2, path: path3, childProcess: childProcess2 } = deps;
|
|
@@ -2616,12 +2683,16 @@ function readChromiumQueue(deps, verified, own) {
|
|
|
2616
2683
|
if (known !== void 0) return known;
|
|
2617
2684
|
let same = pid === process.pid;
|
|
2618
2685
|
if (!same) {
|
|
2686
|
+
let started = "";
|
|
2619
2687
|
try {
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2688
|
+
started = childProcess2.execFileSync("ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8" }).trim();
|
|
2689
|
+
} catch (err) {
|
|
2690
|
+
const gone = err instanceof Error && "status" in err && err.status === 1;
|
|
2691
|
+
if (!gone) return true;
|
|
2624
2692
|
}
|
|
2693
|
+
const startedAt = Date.parse(started);
|
|
2694
|
+
if (started && Number.isNaN(startedAt)) return true;
|
|
2695
|
+
same = Math.abs(startedAt / 1e3 - Number(match[2])) <= 2;
|
|
2625
2696
|
}
|
|
2626
2697
|
verified.set(entry, same);
|
|
2627
2698
|
return same;
|
|
@@ -2741,13 +2812,13 @@ function currentRuntime() {
|
|
|
2741
2812
|
return { platform: process.platform, env: process.env };
|
|
2742
2813
|
}
|
|
2743
2814
|
function processCommand(pid) {
|
|
2744
|
-
return (0,
|
|
2815
|
+
return (0, import_node_child_process2.execFileSync)("/bin/ps", ["-p", String(pid), "-o", "command="], {
|
|
2745
2816
|
encoding: "utf8"
|
|
2746
2817
|
}).trim();
|
|
2747
2818
|
}
|
|
2748
2819
|
function processIdentity(pid) {
|
|
2749
2820
|
try {
|
|
2750
|
-
const identity = (0,
|
|
2821
|
+
const identity = (0, import_node_child_process2.execFileSync)(
|
|
2751
2822
|
"/bin/ps",
|
|
2752
2823
|
["-p", String(pid), "-o", "lstart=", "-o", "command="],
|
|
2753
2824
|
{ encoding: "utf8" }
|
|
@@ -2884,10 +2955,10 @@ function rootChromePid(b) {
|
|
|
2884
2955
|
function killTree(pid) {
|
|
2885
2956
|
let kids = [];
|
|
2886
2957
|
try {
|
|
2887
|
-
kids = (
|
|
2958
|
+
kids = listProcessChildren([pid]);
|
|
2888
2959
|
} catch {
|
|
2889
2960
|
}
|
|
2890
|
-
for (const k of kids) killTree(
|
|
2961
|
+
for (const k of kids) killTree(k);
|
|
2891
2962
|
try {
|
|
2892
2963
|
process.kill(pid, "SIGKILL");
|
|
2893
2964
|
} catch {
|
|
@@ -5867,6 +5938,28 @@ function isAppBootTargetUrl(initUrl) {
|
|
|
5867
5938
|
}
|
|
5868
5939
|
}
|
|
5869
5940
|
|
|
5941
|
+
// cli/maestro-accessibility.ts
|
|
5942
|
+
function accessibilityBounds(node) {
|
|
5943
|
+
const left = Math.trunc(node.frame.x);
|
|
5944
|
+
const top = Math.trunc(node.frame.y);
|
|
5945
|
+
return {
|
|
5946
|
+
x: left,
|
|
5947
|
+
y: top,
|
|
5948
|
+
width: Math.trunc(node.frame.x + node.frame.width) - left,
|
|
5949
|
+
height: Math.trunc(node.frame.y + node.frame.height) - top
|
|
5950
|
+
};
|
|
5951
|
+
}
|
|
5952
|
+
function sameNativeAccessibilityShape(a, b, bounds) {
|
|
5953
|
+
if ((a.testID ?? "") !== (b.testID ?? "") || (a.label ?? "") !== (b.label ?? "") || (a.placeholder ?? "") !== (b.placeholder ?? "") || (a.value ?? "") !== (b.value ?? "") || a.enabled !== b.enabled || a.selected !== b.selected || a.checked !== b.checked || a.clickable !== b.clickable || (a.hasFocus ?? false) !== (b.hasFocus ?? false) || JSON.stringify(bounds(a)) !== JSON.stringify(bounds(b)) || a.children.length !== b.children.length) {
|
|
5954
|
+
return false;
|
|
5955
|
+
}
|
|
5956
|
+
for (const [index, child] of a.children.entries()) {
|
|
5957
|
+
const other = b.children[index];
|
|
5958
|
+
if (!other || !sameNativeAccessibilityShape(child, other, bounds)) return false;
|
|
5959
|
+
}
|
|
5960
|
+
return true;
|
|
5961
|
+
}
|
|
5962
|
+
|
|
5870
5963
|
// cli/commands/inspect/core.ts
|
|
5871
5964
|
function layoutBoundFontFamily(style) {
|
|
5872
5965
|
const raw = typeof style === "object" && style !== null ? style.fontFamily : void 0;
|
|
@@ -6225,6 +6318,7 @@ async function waitForSootsimIdle({
|
|
|
6225
6318
|
stablePolls = 3,
|
|
6226
6319
|
strict = false,
|
|
6227
6320
|
paintStill = false,
|
|
6321
|
+
maestro = false,
|
|
6228
6322
|
motionOnly = false,
|
|
6229
6323
|
transitionStartWindowMs = 80,
|
|
6230
6324
|
transitionTimeoutMs = 4e3
|
|
@@ -6256,12 +6350,15 @@ async function waitForSootsimIdle({
|
|
|
6256
6350
|
const pollMs = ${Math.max(1, Math.round(pollMs))}
|
|
6257
6351
|
const strict = ${strict ? "true" : "false"}
|
|
6258
6352
|
const paintStill = ${paintStill ? "true" : "false"}
|
|
6353
|
+
const maestro = ${maestro ? "true" : "false"}
|
|
6354
|
+
const accessibilityBounds = ${accessibilityBounds.toString()}
|
|
6355
|
+
const sameNativeAccessibilityShape = ${sameNativeAccessibilityShape.toString()}
|
|
6259
6356
|
const motionOnly = ${motionOnly ? "true" : "false"}
|
|
6260
6357
|
// full mounted-geometry observation needs at least two hierarchy reads
|
|
6261
6358
|
// plus the stillness window, which a sub-second budget cannot afford:
|
|
6262
6359
|
// tight budgets (auto-wait) settle on worker stillness plus root
|
|
6263
6360
|
// membership, generous ones confirm the geometry too.
|
|
6264
|
-
const fullGeometry = ${!motionOnly && maxMs >= 1e3 ? "true" : "false"}
|
|
6361
|
+
const fullGeometry = ${!maestro && !motionOnly && maxMs >= 1e3 ? "true" : "false"}
|
|
6265
6362
|
const requiredStillMs = paintStill ? 0 : ${Math.max(1, Math.round(stablePolls)) * Math.max(1, Math.round(pollMs))}
|
|
6266
6363
|
const minimumStablePolls = paintStill ? 1 : ${Math.min(2, Math.max(1, Math.round(stablePolls)))}
|
|
6267
6364
|
const composite = paintStill ? window.SootSim?.bridges?.liveComposite : null
|
|
@@ -6383,6 +6480,9 @@ async function waitForSootsimIdle({
|
|
|
6383
6480
|
// strict also waits out shell motion: a system alert, sheet or menu
|
|
6384
6481
|
// animates in the shell worker while the app's own stats read still,
|
|
6385
6482
|
// so its presentation is complete only once the shell's list empties.
|
|
6483
|
+
const accessibilityRead = maestro
|
|
6484
|
+
? answer(() => window.__sootsimTest.captureAccessibilityTree()).catch(() => null)
|
|
6485
|
+
: null
|
|
6386
6486
|
const motionRead = strict
|
|
6387
6487
|
? answer(() => window.__sootsimTest?.listAnimations?.()).catch(() => null)
|
|
6388
6488
|
: null
|
|
@@ -6392,9 +6492,12 @@ async function waitForSootsimIdle({
|
|
|
6392
6492
|
// the compositor rejects a stats request it is too busy to answer.
|
|
6393
6493
|
const compositorRead = answer(() => window.__sootsimCompositor.getStats()).catch(() => BUSY)
|
|
6394
6494
|
const countsRead = motionOnly ? null : answer(() => window.__sootsimTest?.getRequestCounts?.()).catch(() => null)
|
|
6395
|
-
// mounted-root membership: the
|
|
6396
|
-
// mounts, unmounts or recycles, in
|
|
6397
|
-
|
|
6495
|
+
// mounted-root membership: the count of nodes that can reach the
|
|
6496
|
+
// window moves while the screen mounts, unmounts or recycles, in
|
|
6497
|
+
// either render mode. a screen a pushed one covers or an inactive
|
|
6498
|
+
// tab stays mounted out of the window, so what it mounts is not
|
|
6499
|
+
// screen motion.
|
|
6500
|
+
const nodeCountRead = answer(() => window.__sootsimTest?.getWindowNodeCount?.()).catch(() => null)
|
|
6398
6501
|
// the mounted hierarchy in render-worker mode comes from the test
|
|
6399
6502
|
// bridge: window.__sootsimRoot is an empty placeholder there, so a
|
|
6400
6503
|
// walk over it hashes every screen to the same empty string while
|
|
@@ -6424,7 +6527,7 @@ async function waitForSootsimIdle({
|
|
|
6424
6527
|
const motion = await motionRead
|
|
6425
6528
|
if (motion === BUSY) workerBusy = true
|
|
6426
6529
|
else if (Array.isArray(motion)) {
|
|
6427
|
-
const blocking = motion.filter((anim) => anim.realm === 'shell' && anim.priority !== 'low')
|
|
6530
|
+
const blocking = motion.filter((anim) => anim.realm === 'shell' && anim.priority !== 'low' && anim.visible !== false)
|
|
6428
6531
|
shellAnimating = blocking.length > 0
|
|
6429
6532
|
// name what holds the settle so a timeout points at its owner.
|
|
6430
6533
|
shellBlockers = blocking
|
|
@@ -6456,6 +6559,8 @@ async function waitForSootsimIdle({
|
|
|
6456
6559
|
stats.hasActiveAnims === true ||
|
|
6457
6560
|
stats.hasActiveBlockingNativeAnimations === true ||
|
|
6458
6561
|
(!paintStill && stats.hasPendingBlockingAnimationFrames === true)
|
|
6562
|
+
// the runtime reports only layout work that can reach the window:
|
|
6563
|
+
// a covered screen or inactive tab committing does not hold it.
|
|
6459
6564
|
layoutDirty =
|
|
6460
6565
|
stats.layoutDirty === true && stats.renderRequested === true
|
|
6461
6566
|
// a freshly-pushed screen showing a skeleton is layout-stable
|
|
@@ -6488,6 +6593,11 @@ async function waitForSootsimIdle({
|
|
|
6488
6593
|
const total = await nodeCountRead
|
|
6489
6594
|
if (total === BUSY) workerBusy = true
|
|
6490
6595
|
nodeCount = typeof total === 'number' ? total : null
|
|
6596
|
+
const accessibility = accessibilityRead ? await accessibilityRead : null
|
|
6597
|
+
const nativeHierarchy = Array.isArray(accessibility) && accessibility.length > 0
|
|
6598
|
+
? accessibility
|
|
6599
|
+
: null
|
|
6600
|
+
if (accessibility === BUSY) workerBusy = true
|
|
6491
6601
|
let hierarchy = hierarchyRead ? await hierarchyRead : null
|
|
6492
6602
|
if (hierarchy === BUSY) {
|
|
6493
6603
|
workerBusy = true
|
|
@@ -6568,7 +6678,7 @@ async function waitForSootsimIdle({
|
|
|
6568
6678
|
pixelFrameToken = token
|
|
6569
6679
|
}
|
|
6570
6680
|
}
|
|
6571
|
-
return { layout: nodes.join(';'), screenPixels, animating, shellAnimating, shellBlockers, layoutDirty, pendingFetches, workerBusy, webViewStarting, webViewBlocker, renderStatsAvailable, requestTotal, requestInFlight, appCommits, nodeCount }
|
|
6681
|
+
return { layout: nodes.join(';'), nativeHierarchy, screenPixels, animating, shellAnimating, shellBlockers, layoutDirty, pendingFetches, workerBusy, webViewStarting, webViewBlocker, renderStatsAvailable, requestTotal, requestInFlight, appCommits, nodeCount }
|
|
6572
6682
|
}
|
|
6573
6683
|
|
|
6574
6684
|
// how long generic background network is allowed to keep us waiting AFTER
|
|
@@ -6582,6 +6692,7 @@ async function waitForSootsimIdle({
|
|
|
6582
6692
|
// so the generic request counters are a courtesy, not a gate: honor them
|
|
6583
6693
|
// only within this grace once the screen is visually still.
|
|
6584
6694
|
const networkQuietGraceMs = 1200
|
|
6695
|
+
let lastNativeHierarchy = null
|
|
6585
6696
|
let lastLayout = ''
|
|
6586
6697
|
let lastScreenPixels = null
|
|
6587
6698
|
let screenChangedPolls = 0
|
|
@@ -6609,6 +6720,9 @@ async function waitForSootsimIdle({
|
|
|
6609
6720
|
}
|
|
6610
6721
|
return true
|
|
6611
6722
|
}
|
|
6723
|
+
const hierarchyUnchanged = (current, previous) =>
|
|
6724
|
+
current !== null && previous !== null && current.length === previous.length &&
|
|
6725
|
+
current.every((node, index) => sameNativeAccessibilityShape(node, previous[index], accessibilityBounds))
|
|
6612
6726
|
const IDLE_HELD = { idleHeld: true }
|
|
6613
6727
|
while (true) {
|
|
6614
6728
|
if (clockNow() >= deadline) {
|
|
@@ -6654,7 +6768,7 @@ async function waitForSootsimIdle({
|
|
|
6654
6768
|
// the loop head drains a transition still in flight before it ends.
|
|
6655
6769
|
if (snapshot.workerBusy && clockNow() >= deadline && report) continue
|
|
6656
6770
|
polls++
|
|
6657
|
-
report = { snapshot, layout: lastLayout, screenPixels: lastScreenPixels, requestTotal: lastRequestTotal, appCommits: lastAppCommits, nodeCount: lastNodeCount }
|
|
6771
|
+
report = { snapshot, nativeHierarchy: lastNativeHierarchy, layout: lastLayout, screenPixels: lastScreenPixels, requestTotal: lastRequestTotal, appCommits: lastAppCommits, nodeCount: lastNodeCount }
|
|
6658
6772
|
if (snapshot.layoutDirty) dirtyPolls++
|
|
6659
6773
|
if (snapshot.animating || snapshot.shellAnimating) animatingPolls++
|
|
6660
6774
|
if (snapshot.webViewStarting) webViewStartingPolls++
|
|
@@ -6675,7 +6789,15 @@ async function waitForSootsimIdle({
|
|
|
6675
6789
|
// strictOk and adds shell motion plus the blocking-stats floor. a
|
|
6676
6790
|
// null count or commit reading means the runtime does not report
|
|
6677
6791
|
// it, which reads as stable the way a missing stats block does.
|
|
6678
|
-
|
|
6792
|
+
// native screen checks observe output, not animation ownership. after
|
|
6793
|
+
// its 3 s pixel phase, iOS accepts two equal native TreeNodes even
|
|
6794
|
+
// while paint-only playback continues. overlap hierarchy reads so
|
|
6795
|
+
// neither the gesture nor screenshot deadline grows.
|
|
6796
|
+
const maestroStill = snapshot.screenPixels !== null && !snapshot.workerBusy && !snapshot.webViewStarting && (
|
|
6797
|
+
!screenChanged || (clockNow() - start >= 3000 &&
|
|
6798
|
+
hierarchyUnchanged(snapshot.nativeHierarchy, lastNativeHierarchy))
|
|
6799
|
+
)
|
|
6800
|
+
const visuallyStill = maestro ? maestroStill :
|
|
6679
6801
|
strictOk &&
|
|
6680
6802
|
!snapshot.animating &&
|
|
6681
6803
|
!snapshot.layoutDirty &&
|
|
@@ -6703,7 +6825,7 @@ async function waitForSootsimIdle({
|
|
|
6703
6825
|
// grace (continuous background traffic must not block forever).
|
|
6704
6826
|
if (
|
|
6705
6827
|
stillProven() &&
|
|
6706
|
-
(motionOnly || networkQuiet || clockNow() - visuallyStillSince >= networkQuietGraceMs)
|
|
6828
|
+
(maestro || motionOnly || networkQuiet || clockNow() - visuallyStillSince >= networkQuietGraceMs)
|
|
6707
6829
|
) {
|
|
6708
6830
|
if (transitionWait) {
|
|
6709
6831
|
await transitionWait
|
|
@@ -6715,6 +6837,7 @@ async function waitForSootsimIdle({
|
|
|
6715
6837
|
stillPolls = []
|
|
6716
6838
|
visuallyStillSince = 0
|
|
6717
6839
|
}
|
|
6840
|
+
lastNativeHierarchy = snapshot.nativeHierarchy
|
|
6718
6841
|
lastLayout = snapshot.layout
|
|
6719
6842
|
lastScreenPixels = snapshot.screenPixels
|
|
6720
6843
|
lastRequestTotal = snapshot.requestTotal
|
|
@@ -6737,20 +6860,21 @@ async function waitForSootsimIdle({
|
|
|
6737
6860
|
}
|
|
6738
6861
|
const last = report.snapshot
|
|
6739
6862
|
const blockers = []
|
|
6740
|
-
if (strict && !last.renderStatsAvailable) blockers.push('render stats unavailable')
|
|
6741
|
-
if (last.animating) blockers.push('animations still running')
|
|
6742
|
-
if (last.shellAnimating) blockers.push('shell animations still running (' + last.shellBlockers + ')')
|
|
6743
|
-
if (last.layoutDirty) blockers.push('layout still dirty')
|
|
6744
|
-
if (last.appCommits !== null && report.appCommits !== null && last.appCommits !== report.appCommits) blockers.push('layout commits still landing')
|
|
6745
|
-
if (last.nodeCount !== null && report.nodeCount !== null && last.nodeCount !== report.nodeCount) blockers.push('node count still changing')
|
|
6746
|
-
if (!motionOnly && last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
6863
|
+
if (!maestro && strict && !last.renderStatsAvailable) blockers.push('render stats unavailable')
|
|
6864
|
+
if (!maestro && last.animating) blockers.push('animations still running')
|
|
6865
|
+
if (!maestro && last.shellAnimating) blockers.push('shell animations still running (' + last.shellBlockers + ')')
|
|
6866
|
+
if (!maestro && last.layoutDirty) blockers.push('layout still dirty')
|
|
6867
|
+
if (!maestro && last.appCommits !== null && report.appCommits !== null && last.appCommits !== report.appCommits) blockers.push('layout commits still landing')
|
|
6868
|
+
if (!maestro && last.nodeCount !== null && report.nodeCount !== null && last.nodeCount !== report.nodeCount) blockers.push('node count still changing')
|
|
6869
|
+
if (!maestro && !motionOnly && last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
6747
6870
|
if (last.workerBusy) blockers.push('a render worker too busy to report')
|
|
6748
6871
|
if (last.webViewStarting) blockers.push(last.webViewBlocker || 'webView still starting')
|
|
6749
|
-
if (last.layout !== report.layout) blockers.push('layout still changing')
|
|
6872
|
+
if (!maestro && last.layout !== report.layout) blockers.push('layout still changing')
|
|
6873
|
+
if (maestro && !hierarchyUnchanged(last.nativeHierarchy, report.nativeHierarchy)) blockers.push(last.nativeHierarchy === null ? 'native accessibility hierarchy unavailable' : 'native accessibility hierarchy still changing')
|
|
6750
6874
|
if (paintStill && !last.screenPixels) blockers.push('screen pixels unavailable')
|
|
6751
6875
|
else if (paintStill && !screenUnchanged(last.screenPixels, report.screenPixels)) blockers.push('screen pixels still changing')
|
|
6752
|
-
if (!motionOnly && last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
|
|
6753
|
-
else if (!motionOnly && last.requestTotal !== report.requestTotal) blockers.push('new requests issued')
|
|
6876
|
+
if (!maestro && !motionOnly && last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
|
|
6877
|
+
else if (!maestro && !motionOnly && last.requestTotal !== report.requestTotal) blockers.push('new requests issued')
|
|
6754
6878
|
if (polls < 2) blockers.push('sim too busy to poll twice')
|
|
6755
6879
|
// the last read is still: motion ended too near the deadline for the
|
|
6756
6880
|
// stillness window to hold before it.
|
|
@@ -6850,6 +6974,470 @@ var nativeRuntimeLocation = readBrowserLocation();
|
|
|
6850
6974
|
// ../peach-engine/src/metro-fingerprint-registry-client.ts
|
|
6851
6975
|
var import_metro_fingerprint_registry = require("peachsim/metro-fingerprint-registry");
|
|
6852
6976
|
|
|
6977
|
+
// ../peach-compat/src/wrapper-real-packages.ts
|
|
6978
|
+
var SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES = {
|
|
6979
|
+
expoUiConfirmationDialog: {
|
|
6980
|
+
specifier: "@peach-internal/expo-ui-confirmation-dialog",
|
|
6981
|
+
packageName: "@expo/ui/src/swift-ui/ConfirmationDialog/index.tsx"
|
|
6982
|
+
},
|
|
6983
|
+
expoUiShareLink: {
|
|
6984
|
+
specifier: "@peach-internal/expo-ui-share-link",
|
|
6985
|
+
packageName: "@expo/ui/src/swift-ui/ShareLink/index.tsx"
|
|
6986
|
+
},
|
|
6987
|
+
expoUiNamespace: {
|
|
6988
|
+
specifier: "@peach-internal/expo-ui-namespace",
|
|
6989
|
+
packageName: "@expo/ui/src/swift-ui/Namespace.tsx"
|
|
6990
|
+
},
|
|
6991
|
+
expoUiHost: {
|
|
6992
|
+
specifier: "@peach-internal/expo-ui-host",
|
|
6993
|
+
packageName: "@expo/ui/src/swift-ui/Host/index.tsx"
|
|
6994
|
+
},
|
|
6995
|
+
expoUiBottomSheet: {
|
|
6996
|
+
specifier: "@peach-internal/expo-ui-bottom-sheet",
|
|
6997
|
+
packageName: "@expo/ui/src/swift-ui/BottomSheet/index.tsx"
|
|
6998
|
+
},
|
|
6999
|
+
expoUiTabView: {
|
|
7000
|
+
specifier: "@peach-internal/expo-ui-tab-view",
|
|
7001
|
+
packageName: "@expo/ui/src/swift-ui/TabView/index.tsx"
|
|
7002
|
+
},
|
|
7003
|
+
expoUiForm: {
|
|
7004
|
+
specifier: "@peach-internal/expo-ui-form",
|
|
7005
|
+
packageName: "@expo/ui/src/swift-ui/Form/index.tsx"
|
|
7006
|
+
},
|
|
7007
|
+
expoUiSection: {
|
|
7008
|
+
specifier: "@peach-internal/expo-ui-section",
|
|
7009
|
+
packageName: "@expo/ui/src/swift-ui/Section/index.tsx"
|
|
7010
|
+
},
|
|
7011
|
+
expoUiAccessoryWidgetBackground: {
|
|
7012
|
+
specifier: "@peach-internal/expo-ui-accessory-widget-background",
|
|
7013
|
+
packageName: "@expo/ui/src/swift-ui/AccessoryWidgetBackground/index.tsx"
|
|
7014
|
+
},
|
|
7015
|
+
expoUiGlassEffectContainer: {
|
|
7016
|
+
specifier: "@peach-internal/expo-ui-glass-effect-container",
|
|
7017
|
+
packageName: "@expo/ui/src/swift-ui/GlassEffectContainer/index.tsx"
|
|
7018
|
+
},
|
|
7019
|
+
expoUiContentUnavailableView: {
|
|
7020
|
+
specifier: "@peach-internal/expo-ui-content-unavailable-view",
|
|
7021
|
+
packageName: "@expo/ui/src/swift-ui/ContentUnavailableView/index.tsx"
|
|
7022
|
+
},
|
|
7023
|
+
expoUiColorPicker: {
|
|
7024
|
+
specifier: "@peach-internal/expo-ui-color-picker",
|
|
7025
|
+
packageName: "@expo/ui/src/swift-ui/ColorPicker/index.tsx"
|
|
7026
|
+
},
|
|
7027
|
+
expoUiProgressView: {
|
|
7028
|
+
specifier: "@peach-internal/expo-ui-progress-view",
|
|
7029
|
+
packageName: "@expo/ui/src/swift-ui/ProgressView/index.tsx"
|
|
7030
|
+
},
|
|
7031
|
+
expoUiToggle: {
|
|
7032
|
+
specifier: "@peach-internal/expo-ui-toggle",
|
|
7033
|
+
packageName: "@expo/ui/src/swift-ui/Toggle/index.tsx"
|
|
7034
|
+
},
|
|
7035
|
+
expoUiPicker: {
|
|
7036
|
+
specifier: "@peach-internal/expo-ui-picker",
|
|
7037
|
+
packageName: "@expo/ui/src/swift-ui/Picker/index.tsx"
|
|
7038
|
+
},
|
|
7039
|
+
expoUiDivider: {
|
|
7040
|
+
specifier: "@peach-internal/expo-ui-divider",
|
|
7041
|
+
packageName: "@expo/ui/src/swift-ui/Divider/index.tsx"
|
|
7042
|
+
},
|
|
7043
|
+
expoUiText: {
|
|
7044
|
+
specifier: "@peach-internal/expo-ui-text",
|
|
7045
|
+
packageName: "@expo/ui/src/swift-ui/Text/index.tsx"
|
|
7046
|
+
},
|
|
7047
|
+
expoUiMenu: {
|
|
7048
|
+
specifier: "@peach-internal/expo-ui-menu",
|
|
7049
|
+
packageName: "@expo/ui/src/swift-ui/Menu/index.tsx"
|
|
7050
|
+
},
|
|
7051
|
+
expoUiImage: {
|
|
7052
|
+
specifier: "@peach-internal/expo-ui-image",
|
|
7053
|
+
packageName: "@expo/ui/src/swift-ui/Image/index.tsx"
|
|
7054
|
+
},
|
|
7055
|
+
expoUiAlert: {
|
|
7056
|
+
specifier: "@peach-internal/expo-ui-alert",
|
|
7057
|
+
packageName: "@expo/ui/src/swift-ui/Alert/index.tsx"
|
|
7058
|
+
},
|
|
7059
|
+
expoUiPopover: {
|
|
7060
|
+
specifier: "@peach-internal/expo-ui-popover",
|
|
7061
|
+
packageName: "@expo/ui/src/swift-ui/Popover/index.tsx"
|
|
7062
|
+
},
|
|
7063
|
+
expoUiRNHostView: {
|
|
7064
|
+
specifier: "@peach-internal/expo-ui-rnhost-view",
|
|
7065
|
+
packageName: "@expo/ui/src/swift-ui/RNHostView.tsx"
|
|
7066
|
+
},
|
|
7067
|
+
expoUiOverlay: {
|
|
7068
|
+
specifier: "@peach-internal/expo-ui-overlay",
|
|
7069
|
+
packageName: "@expo/ui/src/swift-ui/Overlay/index.tsx"
|
|
7070
|
+
},
|
|
7071
|
+
expoUiBackground: {
|
|
7072
|
+
specifier: "@peach-internal/expo-ui-background",
|
|
7073
|
+
packageName: "@expo/ui/src/swift-ui/Background/index.tsx"
|
|
7074
|
+
},
|
|
7075
|
+
expoUiMask: {
|
|
7076
|
+
specifier: "@peach-internal/expo-ui-mask",
|
|
7077
|
+
packageName: "@expo/ui/src/swift-ui/Mask/index.tsx"
|
|
7078
|
+
},
|
|
7079
|
+
expoUiShapes: {
|
|
7080
|
+
specifier: "@peach-internal/expo-ui-shapes",
|
|
7081
|
+
packageName: "@expo/ui/src/swift-ui/Shapes/index.tsx"
|
|
7082
|
+
},
|
|
7083
|
+
expoUiControlGroup: {
|
|
7084
|
+
specifier: "@peach-internal/expo-ui-control-group",
|
|
7085
|
+
packageName: "@expo/ui/src/swift-ui/ControlGroup/index.tsx"
|
|
7086
|
+
},
|
|
7087
|
+
expoUiScrollView: {
|
|
7088
|
+
specifier: "@peach-internal/expo-ui-scroll-view",
|
|
7089
|
+
packageName: "@expo/ui/src/swift-ui/ScrollView/index.tsx"
|
|
7090
|
+
},
|
|
7091
|
+
expoUiGrid: {
|
|
7092
|
+
specifier: "@peach-internal/expo-ui-grid",
|
|
7093
|
+
packageName: "@expo/ui/src/swift-ui/Grid/index.tsx"
|
|
7094
|
+
},
|
|
7095
|
+
expoUiGroup: {
|
|
7096
|
+
specifier: "@peach-internal/expo-ui-group",
|
|
7097
|
+
packageName: "@expo/ui/src/swift-ui/Group/index.tsx"
|
|
7098
|
+
},
|
|
7099
|
+
expoUiSpacer: {
|
|
7100
|
+
specifier: "@peach-internal/expo-ui-spacer",
|
|
7101
|
+
packageName: "@expo/ui/src/swift-ui/Spacer/index.tsx"
|
|
7102
|
+
},
|
|
7103
|
+
expoUiLazyHStack: {
|
|
7104
|
+
specifier: "@peach-internal/expo-ui-lazy-hstack",
|
|
7105
|
+
packageName: "@expo/ui/src/swift-ui/LazyHStack/index.tsx"
|
|
7106
|
+
},
|
|
7107
|
+
expoUiLazyVStack: {
|
|
7108
|
+
specifier: "@peach-internal/expo-ui-lazy-vstack",
|
|
7109
|
+
packageName: "@expo/ui/src/swift-ui/LazyVStack/index.tsx"
|
|
7110
|
+
},
|
|
7111
|
+
expoUiHStack: {
|
|
7112
|
+
specifier: "@peach-internal/expo-ui-hstack",
|
|
7113
|
+
packageName: "@expo/ui/src/swift-ui/HStack/index.tsx"
|
|
7114
|
+
},
|
|
7115
|
+
expoUiVStack: {
|
|
7116
|
+
specifier: "@peach-internal/expo-ui-vstack",
|
|
7117
|
+
packageName: "@expo/ui/src/swift-ui/VStack/index.tsx"
|
|
7118
|
+
},
|
|
7119
|
+
expoUiZStack: {
|
|
7120
|
+
specifier: "@peach-internal/expo-ui-zstack",
|
|
7121
|
+
packageName: "@expo/ui/src/swift-ui/ZStack/index.tsx"
|
|
7122
|
+
},
|
|
7123
|
+
expoUiButton: {
|
|
7124
|
+
specifier: "@peach-internal/expo-ui-button",
|
|
7125
|
+
packageName: "@expo/ui/src/swift-ui/Button/index.tsx"
|
|
7126
|
+
},
|
|
7127
|
+
expoUiDatePicker: {
|
|
7128
|
+
specifier: "@peach-internal/expo-ui-date-picker",
|
|
7129
|
+
packageName: "@expo/ui/src/swift-ui/DatePicker/index.tsx"
|
|
7130
|
+
},
|
|
7131
|
+
expoUiSlider: {
|
|
7132
|
+
specifier: "@peach-internal/expo-ui-slider",
|
|
7133
|
+
packageName: "@expo/ui/src/swift-ui/Slider/index.tsx"
|
|
7134
|
+
},
|
|
7135
|
+
expoUiStepper: {
|
|
7136
|
+
specifier: "@peach-internal/expo-ui-stepper",
|
|
7137
|
+
packageName: "@expo/ui/src/swift-ui/Stepper/index.tsx"
|
|
7138
|
+
},
|
|
7139
|
+
expoUiLink: {
|
|
7140
|
+
specifier: "@peach-internal/expo-ui-link",
|
|
7141
|
+
packageName: "@expo/ui/src/swift-ui/Link/index.tsx"
|
|
7142
|
+
},
|
|
7143
|
+
expoUiAnimationConstants: {
|
|
7144
|
+
specifier: "@peach-internal/expo-ui-animation-constants",
|
|
7145
|
+
packageName: "@expo/ui/build/swift-ui/modifiers/animation/constants.js"
|
|
7146
|
+
},
|
|
7147
|
+
expoUiWithAnimation: {
|
|
7148
|
+
specifier: "@peach-internal/expo-ui-with-animation",
|
|
7149
|
+
packageName: "@expo/ui/build/swift-ui/withAnimation.js"
|
|
7150
|
+
},
|
|
7151
|
+
expoUiNativeState: {
|
|
7152
|
+
specifier: "@peach-internal/expo-ui-native-state",
|
|
7153
|
+
packageName: "@expo/ui/build/State/index.js"
|
|
7154
|
+
},
|
|
7155
|
+
expoUiSyncToggle: {
|
|
7156
|
+
specifier: "@peach-internal/expo-ui-sync-toggle",
|
|
7157
|
+
packageName: "@expo/ui/build/swift-ui/SyncToggle/index.js"
|
|
7158
|
+
},
|
|
7159
|
+
expoUiTextField: {
|
|
7160
|
+
specifier: "@peach-internal/expo-ui-text-field",
|
|
7161
|
+
packageName: "@expo/ui/src/swift-ui/TextField/index.tsx"
|
|
7162
|
+
},
|
|
7163
|
+
expoUiSecureField: {
|
|
7164
|
+
specifier: "@peach-internal/expo-ui-secure-field",
|
|
7165
|
+
packageName: "@expo/ui/src/swift-ui/SecureField/index.tsx"
|
|
7166
|
+
},
|
|
7167
|
+
expoUiArrangementView: {
|
|
7168
|
+
specifier: "@peach-internal/expo-ui-arrangement-view",
|
|
7169
|
+
packageName: "@expo/ui/src/swift-ui/ArrangementView/index.tsx"
|
|
7170
|
+
},
|
|
7171
|
+
expoUiLazyHStackForEach: {
|
|
7172
|
+
specifier: "@peach-internal/expo-ui-lazy-hstack-for-each",
|
|
7173
|
+
packageName: "@expo/ui/src/swift-ui/LazyHStack/index.tsx"
|
|
7174
|
+
},
|
|
7175
|
+
expoUiLazyVStackForEach: {
|
|
7176
|
+
specifier: "@peach-internal/expo-ui-lazy-vstack-for-each",
|
|
7177
|
+
packageName: "@expo/ui/src/swift-ui/LazyVStack/index.tsx"
|
|
7178
|
+
},
|
|
7179
|
+
expoUiNavigationDestination: {
|
|
7180
|
+
specifier: "@peach-internal/expo-ui-navigation-destination",
|
|
7181
|
+
packageName: "@expo/ui/src/swift-ui/NavigationDestination/index.tsx"
|
|
7182
|
+
},
|
|
7183
|
+
expoUiNavigationLink: {
|
|
7184
|
+
specifier: "@peach-internal/expo-ui-navigation-link",
|
|
7185
|
+
packageName: "@expo/ui/src/swift-ui/NavigationLink/index.tsx"
|
|
7186
|
+
},
|
|
7187
|
+
expoUiNavigationStack: {
|
|
7188
|
+
specifier: "@peach-internal/expo-ui-navigation-stack",
|
|
7189
|
+
packageName: "@expo/ui/src/swift-ui/NavigationStack/index.tsx"
|
|
7190
|
+
},
|
|
7191
|
+
expoUiNavigationSplitView: {
|
|
7192
|
+
specifier: "@peach-internal/expo-ui-navigation-split-view",
|
|
7193
|
+
packageName: "@expo/ui/src/swift-ui/NavigationSplitView/index.tsx"
|
|
7194
|
+
},
|
|
7195
|
+
expoUiToolbar: {
|
|
7196
|
+
specifier: "@peach-internal/expo-ui-toolbar",
|
|
7197
|
+
packageName: "@expo/ui/src/swift-ui/Toolbar/index.tsx"
|
|
7198
|
+
},
|
|
7199
|
+
expoUiList: {
|
|
7200
|
+
specifier: "@peach-internal/expo-ui-list",
|
|
7201
|
+
packageName: "@expo/ui/src/swift-ui/List/index.tsx"
|
|
7202
|
+
},
|
|
7203
|
+
expoUiDisclosureGroup: {
|
|
7204
|
+
specifier: "@peach-internal/expo-ui-disclosure-group",
|
|
7205
|
+
packageName: "@expo/ui/src/swift-ui/DisclosureGroup/index.tsx"
|
|
7206
|
+
},
|
|
7207
|
+
expoUiGauge: {
|
|
7208
|
+
specifier: "@peach-internal/expo-ui-gauge",
|
|
7209
|
+
packageName: "@expo/ui/src/swift-ui/Gauge/index.tsx"
|
|
7210
|
+
},
|
|
7211
|
+
expoUiLabeledContent: {
|
|
7212
|
+
specifier: "@peach-internal/expo-ui-labeled-content",
|
|
7213
|
+
packageName: "@expo/ui/src/swift-ui/LabeledContent/index.tsx"
|
|
7214
|
+
},
|
|
7215
|
+
expoUiLabel: {
|
|
7216
|
+
specifier: "@peach-internal/expo-ui-label",
|
|
7217
|
+
packageName: "@expo/ui/src/swift-ui/Label/index.tsx"
|
|
7218
|
+
},
|
|
7219
|
+
expoCodedError: {
|
|
7220
|
+
specifier: "@peach-internal/expo-coded-error",
|
|
7221
|
+
packageName: "expo-modules-core/build/errors/CodedError.js"
|
|
7222
|
+
},
|
|
7223
|
+
expoUnavailabilityError: {
|
|
7224
|
+
specifier: "@peach-internal/expo-unavailability-error",
|
|
7225
|
+
packageName: "expo-modules-core/build/errors/UnavailabilityError.js"
|
|
7226
|
+
},
|
|
7227
|
+
expoPlatform: {
|
|
7228
|
+
specifier: "@peach-internal/expo-platform",
|
|
7229
|
+
packageName: "expo-modules-core/build/Platform.js"
|
|
7230
|
+
},
|
|
7231
|
+
expoSharedObjectHook: {
|
|
7232
|
+
specifier: "@peach-internal/expo-shared-object-hook",
|
|
7233
|
+
packageName: "expo-modules-core/build/hooks/useReleasingSharedObject.js"
|
|
7234
|
+
},
|
|
7235
|
+
expoSharedObjectLifecycleHook: {
|
|
7236
|
+
specifier: "@peach-internal/expo-shared-object-lifecycle-hook",
|
|
7237
|
+
packageName: "expo-modules-core/build/hooks/useReleasingSharedObjectWithLifecycle.js"
|
|
7238
|
+
},
|
|
7239
|
+
expoApplication: {
|
|
7240
|
+
specifier: "@sootsim-internal/expo-application-real",
|
|
7241
|
+
packageName: "expo-application"
|
|
7242
|
+
},
|
|
7243
|
+
expoBackgroundFetch: {
|
|
7244
|
+
specifier: "@sootsim-internal/expo-background-fetch-real",
|
|
7245
|
+
packageName: "expo-background-fetch"
|
|
7246
|
+
},
|
|
7247
|
+
expoBackgroundTask: {
|
|
7248
|
+
specifier: "@sootsim-internal/expo-background-task-real",
|
|
7249
|
+
packageName: "expo-background-task"
|
|
7250
|
+
},
|
|
7251
|
+
expoSensors: {
|
|
7252
|
+
specifier: "@sootsim-internal/expo-sensors-real",
|
|
7253
|
+
packageName: "expo-sensors"
|
|
7254
|
+
},
|
|
7255
|
+
expoBattery: {
|
|
7256
|
+
specifier: "@sootsim-internal/expo-battery-real",
|
|
7257
|
+
packageName: "expo-battery"
|
|
7258
|
+
},
|
|
7259
|
+
expoBrightness: {
|
|
7260
|
+
specifier: "@sootsim-internal/expo-brightness-real",
|
|
7261
|
+
packageName: "expo-brightness"
|
|
7262
|
+
},
|
|
7263
|
+
expoConstants: {
|
|
7264
|
+
specifier: "@sootsim-internal/expo-constants-real",
|
|
7265
|
+
packageName: "expo-constants"
|
|
7266
|
+
},
|
|
7267
|
+
expoCalendar: {
|
|
7268
|
+
specifier: "@sootsim-internal/expo-calendar-real",
|
|
7269
|
+
packageName: "expo-calendar"
|
|
7270
|
+
},
|
|
7271
|
+
expoCalendarLegacy: {
|
|
7272
|
+
specifier: "@sootsim-internal/expo-calendar-legacy-real",
|
|
7273
|
+
// the package's own `./legacy` export, not a hardcoded `src/legacy/...`
|
|
7274
|
+
// path — this follows wherever upstream points the subpath, in every
|
|
7275
|
+
// version that has one. versions without it never import the legacy
|
|
7276
|
+
// stub, so the alias just goes unused there.
|
|
7277
|
+
packageName: "expo-calendar/legacy"
|
|
7278
|
+
},
|
|
7279
|
+
expoCellular: {
|
|
7280
|
+
specifier: "@sootsim-internal/expo-cellular-real",
|
|
7281
|
+
packageName: "expo-cellular"
|
|
7282
|
+
},
|
|
7283
|
+
expoContactsContacts: {
|
|
7284
|
+
specifier: "@sootsim-internal/expo-contacts-contacts",
|
|
7285
|
+
// sdk 57 split Contacts.ts into src/index.ts + legacy/ + next/
|
|
7286
|
+
packageName: "expo-contacts/src/index.ts"
|
|
7287
|
+
},
|
|
7288
|
+
expoContactsContactAccessButton: {
|
|
7289
|
+
specifier: "@sootsim-internal/expo-contacts-contact-access-button",
|
|
7290
|
+
packageName: "expo-contacts/src/ContactAccessButton.tsx"
|
|
7291
|
+
},
|
|
7292
|
+
expoContactsLegacy: {
|
|
7293
|
+
specifier: "@sootsim-internal/expo-contacts-legacy-real",
|
|
7294
|
+
// same as expoCalendarLegacy: the public `./legacy` export, not a src path.
|
|
7295
|
+
packageName: "expo-contacts/legacy"
|
|
7296
|
+
},
|
|
7297
|
+
expoInsights: {
|
|
7298
|
+
specifier: "@sootsim-internal/expo-insights-real",
|
|
7299
|
+
packageName: "expo-insights"
|
|
7300
|
+
},
|
|
7301
|
+
expoIntentLauncher: {
|
|
7302
|
+
specifier: "@sootsim-internal/expo-intent-launcher-real",
|
|
7303
|
+
packageName: "expo-intent-launcher"
|
|
7304
|
+
},
|
|
7305
|
+
expoMailComposer: {
|
|
7306
|
+
specifier: "@sootsim-internal/expo-mail-composer-real",
|
|
7307
|
+
packageName: "expo-mail-composer"
|
|
7308
|
+
},
|
|
7309
|
+
expoNetwork: {
|
|
7310
|
+
specifier: "@sootsim-internal/expo-network-real",
|
|
7311
|
+
packageName: "expo-network"
|
|
7312
|
+
},
|
|
7313
|
+
expoPrint: {
|
|
7314
|
+
specifier: "@sootsim-internal/expo-print-real",
|
|
7315
|
+
packageName: "expo-print"
|
|
7316
|
+
},
|
|
7317
|
+
expoScreenCapture: {
|
|
7318
|
+
specifier: "@sootsim-internal/expo-screen-capture-real",
|
|
7319
|
+
packageName: "expo-screen-capture"
|
|
7320
|
+
},
|
|
7321
|
+
expoScreenOrientation: {
|
|
7322
|
+
specifier: "@sootsim-internal/expo-screen-orientation-real",
|
|
7323
|
+
packageName: "expo-screen-orientation"
|
|
7324
|
+
},
|
|
7325
|
+
expoQuickActions: {
|
|
7326
|
+
specifier: "@sootsim-internal/expo-quick-actions-real",
|
|
7327
|
+
packageName: "expo-quick-actions/build/index.js"
|
|
7328
|
+
},
|
|
7329
|
+
expoSecureStore: {
|
|
7330
|
+
specifier: "@sootsim-internal/expo-secure-store-real",
|
|
7331
|
+
packageName: "expo-secure-store"
|
|
7332
|
+
},
|
|
7333
|
+
expoSplashScreen: {
|
|
7334
|
+
specifier: "@sootsim-internal/expo-splash-screen-real",
|
|
7335
|
+
packageName: "expo-splash-screen"
|
|
7336
|
+
},
|
|
7337
|
+
expoSqlite: {
|
|
7338
|
+
specifier: "@sootsim-internal/expo-sqlite-real",
|
|
7339
|
+
packageName: "expo-sqlite"
|
|
7340
|
+
},
|
|
7341
|
+
expoLinearGradient: {
|
|
7342
|
+
specifier: "@sootsim-internal/expo-linear-gradient-real",
|
|
7343
|
+
packageName: "expo-linear-gradient"
|
|
7344
|
+
},
|
|
7345
|
+
expoBlur: {
|
|
7346
|
+
specifier: "@sootsim-internal/expo-blur-real",
|
|
7347
|
+
packageName: "expo-blur"
|
|
7348
|
+
},
|
|
7349
|
+
expoSymbols: {
|
|
7350
|
+
specifier: "@sootsim-internal/expo-symbols-real",
|
|
7351
|
+
packageName: "expo-symbols"
|
|
7352
|
+
},
|
|
7353
|
+
communityCheckbox: {
|
|
7354
|
+
specifier: "@sootsim-internal/react-native-community-checkbox-real",
|
|
7355
|
+
packageName: "@react-native-community/checkbox/dist/js/CheckBox.ios.js"
|
|
7356
|
+
},
|
|
7357
|
+
reactNativeMaskedView: {
|
|
7358
|
+
specifier: "@sootsim-internal/masked-view-real",
|
|
7359
|
+
packageName: "@react-native-masked-view/masked-view"
|
|
7360
|
+
},
|
|
7361
|
+
expoSharing: {
|
|
7362
|
+
specifier: "@sootsim-internal/expo-sharing-real",
|
|
7363
|
+
packageName: "expo-sharing"
|
|
7364
|
+
},
|
|
7365
|
+
expoSms: {
|
|
7366
|
+
specifier: "@sootsim-internal/expo-sms-real",
|
|
7367
|
+
packageName: "expo-sms"
|
|
7368
|
+
},
|
|
7369
|
+
expoSpeech: {
|
|
7370
|
+
specifier: "@sootsim-internal/expo-speech-real",
|
|
7371
|
+
packageName: "expo-speech"
|
|
7372
|
+
},
|
|
7373
|
+
expoStoreReview: {
|
|
7374
|
+
specifier: "@sootsim-internal/expo-store-review-real",
|
|
7375
|
+
packageName: "expo-store-review"
|
|
7376
|
+
},
|
|
7377
|
+
expoTaskManager: {
|
|
7378
|
+
specifier: "@sootsim-internal/expo-task-manager-real",
|
|
7379
|
+
packageName: "expo-task-manager"
|
|
7380
|
+
},
|
|
7381
|
+
expoTrackingTransparency: {
|
|
7382
|
+
specifier: "@sootsim-internal/expo-tracking-transparency-real",
|
|
7383
|
+
packageName: "expo-tracking-transparency"
|
|
7384
|
+
},
|
|
7385
|
+
expoVideoThumbnails: {
|
|
7386
|
+
specifier: "@sootsim-internal/expo-video-thumbnails-real",
|
|
7387
|
+
packageName: "expo-video-thumbnails"
|
|
7388
|
+
},
|
|
7389
|
+
googleSignin: {
|
|
7390
|
+
specifier: "@sootsim-internal/react-native-google-signin-real",
|
|
7391
|
+
packageName: "@react-native-google-signin/google-signin"
|
|
7392
|
+
},
|
|
7393
|
+
reactNativeHapticFeedback: {
|
|
7394
|
+
specifier: "@sootsim-internal/react-native-haptic-feedback-real",
|
|
7395
|
+
packageName: "react-native-haptic-feedback"
|
|
7396
|
+
},
|
|
7397
|
+
reactNativeSegmentedControl: {
|
|
7398
|
+
specifier: "@sootsim-internal/react-native-segmented-control-real",
|
|
7399
|
+
packageName: "@react-native-segmented-control/segmented-control/js/SegmentedControl.ios.js"
|
|
7400
|
+
},
|
|
7401
|
+
reactNativeUitextview: {
|
|
7402
|
+
specifier: "@sootsim-internal/react-native-uitextview-real",
|
|
7403
|
+
packageName: "react-native-uitextview"
|
|
7404
|
+
},
|
|
7405
|
+
reactNativeWorkletsBundleMode: {
|
|
7406
|
+
specifier: "@sootsim-internal/react-native-worklets-bundle-mode-real",
|
|
7407
|
+
packageName: "react-native-worklets/lib/module/debug/bundleMode.native.js"
|
|
7408
|
+
},
|
|
7409
|
+
reactNativeWorkletsFunction: {
|
|
7410
|
+
specifier: "@peach-internal/react-native-worklets-function-real",
|
|
7411
|
+
packageName: "react-native-worklets/lib/module/workletFunction.js"
|
|
7412
|
+
},
|
|
7413
|
+
reactNativeWorkletsRunLoop: {
|
|
7414
|
+
specifier: "@sootsim-internal/react-native-worklets-run-loop-real",
|
|
7415
|
+
packageName: "react-native-worklets/lib/module/runLoop/workletRuntime/index.js"
|
|
7416
|
+
}
|
|
7417
|
+
};
|
|
7418
|
+
var PEACH_REACT_NATIVE_UPSTREAM_MODULES = {
|
|
7419
|
+
reactNativeBatchedBridge: {
|
|
7420
|
+
specifier: "@peach-internal/react-native/BatchedBridge/BatchedBridge",
|
|
7421
|
+
packageName: "react-native/Libraries/BatchedBridge/BatchedBridge.js"
|
|
7422
|
+
},
|
|
7423
|
+
reactNativeStyleAttributes: {
|
|
7424
|
+
specifier: "@peach-internal/react-native/Components/View/ReactNativeStyleAttributes",
|
|
7425
|
+
packageName: "react-native/Libraries/Components/View/ReactNativeStyleAttributes.js"
|
|
7426
|
+
},
|
|
7427
|
+
reactNativeProcessColor: {
|
|
7428
|
+
specifier: "@peach-internal/react-native/StyleSheet/processColor",
|
|
7429
|
+
packageName: "react-native/Libraries/StyleSheet/processColor.js"
|
|
7430
|
+
},
|
|
7431
|
+
reactNativeFontVariationSettings: {
|
|
7432
|
+
specifier: "@peach-internal/react-native-font-variation-settings",
|
|
7433
|
+
packageName: "react-native/Libraries/StyleSheet/processFontVariationSettings.js"
|
|
7434
|
+
}
|
|
7435
|
+
};
|
|
7436
|
+
var PEACH_UPSTREAM_MODULES = {
|
|
7437
|
+
...SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES,
|
|
7438
|
+
...PEACH_REACT_NATIVE_UPSTREAM_MODULES
|
|
7439
|
+
};
|
|
7440
|
+
|
|
6853
7441
|
// ../peach-engine/src/metro-fingerprint.ts
|
|
6854
7442
|
var import_metro_production_bundle2 = require("peachsim/metro-production-bundle");
|
|
6855
7443
|
var import_react_native_host_modules = require("peachsim/react-native-host-modules");
|
|
@@ -6910,7 +7498,8 @@ var peachPublicBrand = Object.freeze({
|
|
|
6910
7498
|
packageName: "peachsim",
|
|
6911
7499
|
commandName: "peach",
|
|
6912
7500
|
domain: "peachsim.com",
|
|
6913
|
-
origin: "https://peachsim.com"
|
|
7501
|
+
origin: "https://peachsim.com",
|
|
7502
|
+
boxOrigin: "https://rnx-box.contrast.dev"
|
|
6914
7503
|
});
|
|
6915
7504
|
var rnxPublicBrand2 = peachPublicBrand;
|
|
6916
7505
|
|
|
@@ -9252,10 +9841,6 @@ function buildComm() {
|
|
|
9252
9841
|
return () => null;
|
|
9253
9842
|
}
|
|
9254
9843
|
function build() {
|
|
9255
|
-
const envPpid = Number(process.env.PPID);
|
|
9256
|
-
if (Number.isFinite(envPpid) && envPpid > 1 && envPpid !== process.ppid) {
|
|
9257
|
-
return () => envPpid;
|
|
9258
|
-
}
|
|
9259
9844
|
if (process.platform === "linux") return buildLinux();
|
|
9260
9845
|
if (process.platform === "darwin") {
|
|
9261
9846
|
const ffi = tryBuildDarwinFfi();
|
|
@@ -9418,24 +10003,24 @@ function tryBuildDarwinPgidFfi() {
|
|
|
9418
10003
|
|
|
9419
10004
|
// cli/secure-file.ts
|
|
9420
10005
|
var import_node_crypto = require("node:crypto");
|
|
9421
|
-
var
|
|
10006
|
+
var import_node_fs2 = require("node:fs");
|
|
9422
10007
|
var import_node_path = require("node:path");
|
|
9423
10008
|
function writeSecureJsonAtomic(filepath, value) {
|
|
9424
|
-
(0,
|
|
10009
|
+
(0, import_node_fs2.mkdirSync)((0, import_node_path.dirname)(filepath), { recursive: true });
|
|
9425
10010
|
const temporary = `${filepath}.tmp-${process.pid}-${(0, import_node_crypto.randomUUID)()}`;
|
|
9426
10011
|
let descriptor = null;
|
|
9427
10012
|
try {
|
|
9428
|
-
descriptor = (0,
|
|
9429
|
-
(0,
|
|
9430
|
-
(0,
|
|
10013
|
+
descriptor = (0, import_node_fs2.openSync)(temporary, "wx", 384);
|
|
10014
|
+
(0, import_node_fs2.fchmodSync)(descriptor, 384);
|
|
10015
|
+
(0, import_node_fs2.writeFileSync)(descriptor, `${JSON.stringify(value, null, 2)}
|
|
9431
10016
|
`);
|
|
9432
|
-
(0,
|
|
9433
|
-
(0,
|
|
10017
|
+
(0, import_node_fs2.fsyncSync)(descriptor);
|
|
10018
|
+
(0, import_node_fs2.closeSync)(descriptor);
|
|
9434
10019
|
descriptor = null;
|
|
9435
|
-
(0,
|
|
10020
|
+
(0, import_node_fs2.renameSync)(temporary, filepath);
|
|
9436
10021
|
} catch (error) {
|
|
9437
|
-
if (descriptor !== null) (0,
|
|
9438
|
-
(0,
|
|
10022
|
+
if (descriptor !== null) (0, import_node_fs2.closeSync)(descriptor);
|
|
10023
|
+
(0, import_node_fs2.rmSync)(temporary, { force: true });
|
|
9439
10024
|
throw error;
|
|
9440
10025
|
}
|
|
9441
10026
|
}
|
|
@@ -10848,6 +11433,9 @@ var BASE_FONT_URLS = [SF_PRO_FONT_URL];
|
|
|
10848
11433
|
var BOOT_FONT_URLS = [...BASE_FONT_URLS];
|
|
10849
11434
|
var PLATFORM_FONT_FAMILIES = [DEFAULT_FONT_FAMILY, EMOJI_FONT_FAMILY];
|
|
10850
11435
|
var _registeredFamilies = new Set(PLATFORM_FONT_FAMILIES);
|
|
11436
|
+
var _registeredFamiliesByFold = new Map(
|
|
11437
|
+
PLATFORM_FONT_FAMILIES.map((family) => [family.toLowerCase(), family])
|
|
11438
|
+
);
|
|
10851
11439
|
|
|
10852
11440
|
// ../peach-engine/src/engine/scroll-momentum-math.ts
|
|
10853
11441
|
var IOS_STATUS_BAR_SCROLL_TO_TOP_RESPONSE_SECONDS = 0.6;
|
|
@@ -11323,72 +11911,269 @@ async function dispatchTwoFingerGesture(page, startA, startB, endA, endB, option
|
|
|
11323
11911
|
await page.waitForTimeout(250);
|
|
11324
11912
|
}
|
|
11325
11913
|
|
|
11326
|
-
// detox/
|
|
11327
|
-
var
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
function scrollOffsetOf(node) {
|
|
11339
|
-
return { x: node?.scrollOffsetX ?? 0, y: node?.scrollOffsetY ?? 0 };
|
|
11340
|
-
}
|
|
11341
|
-
function visibleFraction(node) {
|
|
11342
|
-
const totalArea = (node?.layout?.width ?? 0) * (node?.layout?.height ?? 0);
|
|
11343
|
-
const frame = node?.visibleFrame;
|
|
11344
|
-
if (totalArea <= 0 || typeof frame?.area !== "number") return 0;
|
|
11345
|
-
return frame.area / totalArea;
|
|
11346
|
-
}
|
|
11347
|
-
function isNodeVisible(node) {
|
|
11348
|
-
return visibleFraction(node) >= DEFAULT_VISIBILITY_THRESHOLD;
|
|
11914
|
+
// detox/navigation-lifecycle.ts
|
|
11915
|
+
var import_attempt_events = __toESM(require_attempt_events(), 1);
|
|
11916
|
+
var DIAGNOSTIC_LIMIT = 40;
|
|
11917
|
+
var pageDiagnostics = /* @__PURE__ */ new WeakMap();
|
|
11918
|
+
var activeNavigations = /* @__PURE__ */ new WeakMap();
|
|
11919
|
+
var lastNavigations = /* @__PURE__ */ new WeakMap();
|
|
11920
|
+
var nextNavigationIdentity = 0;
|
|
11921
|
+
var persistedDiagnostics = /* @__PURE__ */ new WeakSet();
|
|
11922
|
+
function persistDiagnostic(diagnostic) {
|
|
11923
|
+
if (persistedDiagnostics.has(diagnostic)) return;
|
|
11924
|
+
persistedDiagnostics.add(diagnostic);
|
|
11925
|
+
(0, import_attempt_events.writeAttemptEvent)(diagnostic);
|
|
11349
11926
|
}
|
|
11350
|
-
function
|
|
11351
|
-
|
|
11927
|
+
function recordPageDiagnostic(page, diagnostic, persist = false) {
|
|
11928
|
+
const entries = pageDiagnostics.get(page);
|
|
11929
|
+
if (!entries) return;
|
|
11930
|
+
entries.push(diagnostic);
|
|
11931
|
+
if (entries.length > DIAGNOSTIC_LIMIT) entries.shift();
|
|
11932
|
+
if (persist) persistDiagnostic(diagnostic);
|
|
11352
11933
|
}
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11934
|
+
function recordGuestError(page, diagnostic) {
|
|
11935
|
+
recordPageDiagnostic(page, diagnostic);
|
|
11936
|
+
for (const entry of pageDiagnostics.get(page) ?? []) persistDiagnostic(entry);
|
|
11356
11937
|
}
|
|
11357
|
-
|
|
11358
|
-
if (
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11938
|
+
function isTopLevelDocumentRequest(page, request) {
|
|
11939
|
+
if (!request.isNavigationRequest() || request.resourceType() !== "document") {
|
|
11940
|
+
return false;
|
|
11941
|
+
}
|
|
11942
|
+
try {
|
|
11943
|
+
return request.frame() === page.mainFrame();
|
|
11944
|
+
} catch {
|
|
11945
|
+
return false;
|
|
11946
|
+
}
|
|
11363
11947
|
}
|
|
11364
|
-
function
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
bottom: absY + (node.layout?.height ?? 0)
|
|
11948
|
+
function recordNavigationMilestoneFor(page, active, milestone, details = {}) {
|
|
11949
|
+
recordPageDiagnostic(
|
|
11950
|
+
page,
|
|
11951
|
+
{
|
|
11952
|
+
...active,
|
|
11953
|
+
...details,
|
|
11954
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11955
|
+
milestone,
|
|
11956
|
+
target: process.env.CONFORMANCE_PROOF_TARGET || "sootsim",
|
|
11957
|
+
type: "rnx-navigation",
|
|
11958
|
+
url: details.url ?? active.navigationUrl
|
|
11376
11959
|
},
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
threshold: DEFAULT_VISIBILITY_THRESHOLD,
|
|
11380
|
-
style: node.style ?? null
|
|
11381
|
-
});
|
|
11960
|
+
true
|
|
11961
|
+
);
|
|
11382
11962
|
}
|
|
11383
|
-
function
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
};
|
|
11963
|
+
function recordNavigationMilestone(page, milestone, details = {}) {
|
|
11964
|
+
const active = activeNavigations.get(page);
|
|
11965
|
+
if (active) recordNavigationMilestoneFor(page, active, milestone, details);
|
|
11387
11966
|
}
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
|
|
11967
|
+
function attachPageDiagnostics(page) {
|
|
11968
|
+
if (pageDiagnostics.has(page)) return;
|
|
11969
|
+
pageDiagnostics.set(page, []);
|
|
11970
|
+
page.on("console", (message) => {
|
|
11971
|
+
const diagnostic = {
|
|
11972
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11973
|
+
level: message.type(),
|
|
11974
|
+
message: message.text(),
|
|
11975
|
+
type: "page-console"
|
|
11976
|
+
};
|
|
11977
|
+
if (message.type() === "error") recordGuestError(page, diagnostic);
|
|
11978
|
+
else recordPageDiagnostic(page, diagnostic);
|
|
11979
|
+
});
|
|
11980
|
+
page.on("pageerror", (error) => {
|
|
11981
|
+
recordGuestError(page, {
|
|
11982
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11983
|
+
message: error.message,
|
|
11984
|
+
type: "page-error"
|
|
11985
|
+
});
|
|
11986
|
+
});
|
|
11987
|
+
page.on("request", (request) => {
|
|
11988
|
+
if (!isTopLevelDocumentRequest(page, request)) return;
|
|
11989
|
+
recordNavigationMilestone(page, "document-request", {
|
|
11990
|
+
method: request.method(),
|
|
11991
|
+
url: request.url()
|
|
11992
|
+
});
|
|
11993
|
+
});
|
|
11994
|
+
page.on("response", (response) => {
|
|
11995
|
+
const request = response.request();
|
|
11996
|
+
if (!isTopLevelDocumentRequest(page, request)) return;
|
|
11997
|
+
recordNavigationMilestone(page, "document-response", {
|
|
11998
|
+
headersReceived: true,
|
|
11999
|
+
status: response.status(),
|
|
12000
|
+
url: request.url()
|
|
12001
|
+
});
|
|
12002
|
+
});
|
|
12003
|
+
page.on("requestfinished", (request) => {
|
|
12004
|
+
if (!isTopLevelDocumentRequest(page, request)) return;
|
|
12005
|
+
recordNavigationMilestone(page, "document-request-finished", { url: request.url() });
|
|
12006
|
+
});
|
|
12007
|
+
page.on("requestfailed", (request) => {
|
|
12008
|
+
const failure = request.failure();
|
|
12009
|
+
const errorText = failure?.errorText ?? "";
|
|
12010
|
+
if (isTopLevelDocumentRequest(page, request)) {
|
|
12011
|
+
recordNavigationMilestone(page, "document-request-failed", {
|
|
12012
|
+
errorText,
|
|
12013
|
+
url: request.url()
|
|
12014
|
+
});
|
|
12015
|
+
return;
|
|
12016
|
+
}
|
|
12017
|
+
recordPageDiagnostic(page, {
|
|
12018
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12019
|
+
errorText,
|
|
12020
|
+
method: request.method(),
|
|
12021
|
+
type: "subresource-request-failed",
|
|
12022
|
+
url: request.url()
|
|
12023
|
+
});
|
|
12024
|
+
});
|
|
12025
|
+
page.on("domcontentloaded", () => {
|
|
12026
|
+
recordNavigationMilestone(page, "domcontentloaded");
|
|
12027
|
+
});
|
|
12028
|
+
page.on("load", () => {
|
|
12029
|
+
recordNavigationMilestone(page, "load");
|
|
12030
|
+
});
|
|
12031
|
+
}
|
|
12032
|
+
async function readSootsimPageState(page) {
|
|
12033
|
+
try {
|
|
12034
|
+
return await page.evaluate(() => {
|
|
12035
|
+
const bootMarks = Reflect.get(window, "__sootsimBootMarks");
|
|
12036
|
+
return {
|
|
12037
|
+
bodyText: document.body?.innerText?.slice(0, 500) ?? "",
|
|
12038
|
+
bootStage: document.documentElement.dataset.sootsimBootStage ?? null,
|
|
12039
|
+
bootMarks: Array.isArray(bootMarks) ? bootMarks.slice(-16) : [],
|
|
12040
|
+
capturedAtEpochMs: Date.now(),
|
|
12041
|
+
bridges: {
|
|
12042
|
+
sootsim: Boolean(window.SootSim),
|
|
12043
|
+
test: Boolean(window.__sootsimTest)
|
|
12044
|
+
},
|
|
12045
|
+
globals: Object.keys(window).filter((key) => key.startsWith("__sootsim") || key === "SootSim").sort(),
|
|
12046
|
+
readyState: document.readyState,
|
|
12047
|
+
title: document.title,
|
|
12048
|
+
url: window.location.href
|
|
12049
|
+
};
|
|
12050
|
+
});
|
|
12051
|
+
} catch (error) {
|
|
12052
|
+
return {
|
|
12053
|
+
evaluateError: error instanceof Error ? error.message : String(error)
|
|
12054
|
+
};
|
|
12055
|
+
}
|
|
12056
|
+
}
|
|
12057
|
+
async function describeSootsimBridgeFailure(page, cause, summary = "timed out waiting for sootsim test bridge", pageState) {
|
|
12058
|
+
const recordBridgeFailure = pageState === void 0;
|
|
12059
|
+
const state = pageState ?? await readSootsimPageState(page);
|
|
12060
|
+
const navigation = lastNavigations.get(page);
|
|
12061
|
+
if (recordBridgeFailure && navigation) {
|
|
12062
|
+
recordNavigationMilestoneFor(page, navigation, "error", {
|
|
12063
|
+
errorText: cause instanceof Error ? cause.message : String(cause),
|
|
12064
|
+
failurePhase: "bridge",
|
|
12065
|
+
pageState: state
|
|
12066
|
+
});
|
|
12067
|
+
}
|
|
12068
|
+
return new Error(
|
|
12069
|
+
[
|
|
12070
|
+
summary,
|
|
12071
|
+
`cause: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
12072
|
+
`page: ${JSON.stringify(state)}`,
|
|
12073
|
+
`recent page diagnostics:
|
|
12074
|
+
${JSON.stringify(getSootsimNavigationDiagnostics(page))}`
|
|
12075
|
+
].join("\n")
|
|
12076
|
+
);
|
|
12077
|
+
}
|
|
12078
|
+
async function navigateSootsimPage(page, url, identity) {
|
|
12079
|
+
attachPageDiagnostics(page);
|
|
12080
|
+
const navigation = {
|
|
12081
|
+
...identity,
|
|
12082
|
+
navigationUrl: url,
|
|
12083
|
+
navigationId: ++nextNavigationIdentity
|
|
12084
|
+
};
|
|
12085
|
+
activeNavigations.set(page, navigation);
|
|
12086
|
+
lastNavigations.set(page, navigation);
|
|
12087
|
+
recordNavigationMilestone(page, "start");
|
|
12088
|
+
try {
|
|
12089
|
+
return await page.goto(url, { waitUntil: "load", timeout: 3e4 });
|
|
12090
|
+
} catch (error) {
|
|
12091
|
+
const pageState = await readSootsimPageState(page);
|
|
12092
|
+
recordNavigationMilestone(page, "error", {
|
|
12093
|
+
errorText: error instanceof Error ? error.message : String(error),
|
|
12094
|
+
failurePhase: "navigation",
|
|
12095
|
+
pageState
|
|
12096
|
+
});
|
|
12097
|
+
throw await describeSootsimBridgeFailure(
|
|
12098
|
+
page,
|
|
12099
|
+
error,
|
|
12100
|
+
"sootsim navigation failed",
|
|
12101
|
+
pageState
|
|
12102
|
+
);
|
|
12103
|
+
} finally {
|
|
12104
|
+
activeNavigations.delete(page);
|
|
12105
|
+
}
|
|
12106
|
+
}
|
|
12107
|
+
function getSootsimNavigationDiagnostics(page) {
|
|
12108
|
+
return [...pageDiagnostics.get(page) ?? []];
|
|
12109
|
+
}
|
|
12110
|
+
|
|
12111
|
+
// detox/expectations.ts
|
|
12112
|
+
var DEFAULT_VISIBILITY_THRESHOLD = 0.75;
|
|
12113
|
+
async function scrollMatcherElement(page, findNode, matcher, pixels, direction, startPositionX, startPositionY) {
|
|
12114
|
+
const node = await findNode(matcher);
|
|
12115
|
+
if (!node) {
|
|
12116
|
+
throw new Error(`scroll container not found: ${JSON.stringify(matcher)}`);
|
|
12117
|
+
}
|
|
12118
|
+
const before = scrollOffsetOf(node);
|
|
12119
|
+
await dragScrollNode(page, node, pixels, direction, startPositionX, startPositionY);
|
|
12120
|
+
const after = scrollOffsetOf(await findNode(matcher));
|
|
12121
|
+
return Math.abs(after.x - before.x) + Math.abs(after.y - before.y);
|
|
12122
|
+
}
|
|
12123
|
+
function scrollOffsetOf(node) {
|
|
12124
|
+
return { x: node?.scrollOffsetX ?? 0, y: node?.scrollOffsetY ?? 0 };
|
|
12125
|
+
}
|
|
12126
|
+
function visibleFraction(node) {
|
|
12127
|
+
const totalArea = (node?.layout?.width ?? 0) * (node?.layout?.height ?? 0);
|
|
12128
|
+
const frame = node?.visibleFrame;
|
|
12129
|
+
if (totalArea <= 0 || typeof frame?.area !== "number") return 0;
|
|
12130
|
+
return frame.area / totalArea;
|
|
12131
|
+
}
|
|
12132
|
+
function isNodeVisible(node) {
|
|
12133
|
+
return visibleFraction(node) >= DEFAULT_VISIBILITY_THRESHOLD;
|
|
12134
|
+
}
|
|
12135
|
+
function focusIsWithin(focused, nodeId) {
|
|
12136
|
+
return focused.nodeId === nodeId || focused.ancestorNodeIds.includes(nodeId);
|
|
12137
|
+
}
|
|
12138
|
+
async function isTextInputNodeFocused(node, page) {
|
|
12139
|
+
const focused = await page.evaluate(async () => window.__sootsimTest.getFocusedNode());
|
|
12140
|
+
return focused !== null && focusIsWithin(focused, node.nodeId);
|
|
12141
|
+
}
|
|
12142
|
+
async function isNodeFocused(node, page) {
|
|
12143
|
+
if (node.isTextInput) return isTextInputNodeFocused(node, page);
|
|
12144
|
+
return page.evaluate(
|
|
12145
|
+
(nodeId) => document.activeElement?.getAttribute("data-sootsim-id") === String(nodeId),
|
|
12146
|
+
node.nodeId
|
|
12147
|
+
);
|
|
12148
|
+
}
|
|
12149
|
+
function describeNodeVisibility(node) {
|
|
12150
|
+
if (!node) return "not found";
|
|
12151
|
+
const absX = node.absolutePosition?.x ?? node.layout?.x ?? 0;
|
|
12152
|
+
const absY = node.absolutePosition?.y ?? node.layout?.y ?? 0;
|
|
12153
|
+
return JSON.stringify({
|
|
12154
|
+
layout: node.layout,
|
|
12155
|
+
absolutePosition: node.absolutePosition ?? null,
|
|
12156
|
+
frame: {
|
|
12157
|
+
x: absX,
|
|
12158
|
+
y: absY,
|
|
12159
|
+
right: absX + (node.layout?.width ?? 0),
|
|
12160
|
+
bottom: absY + (node.layout?.height ?? 0)
|
|
12161
|
+
},
|
|
12162
|
+
visibleFrame: node.visibleFrame ?? null,
|
|
12163
|
+
visibleFraction: visibleFraction(node),
|
|
12164
|
+
threshold: DEFAULT_VISIBILITY_THRESHOLD,
|
|
12165
|
+
style: node.style ?? null
|
|
12166
|
+
});
|
|
12167
|
+
}
|
|
12168
|
+
function createExpect(findNode, getPage2) {
|
|
12169
|
+
return function sootsimExpect2(el) {
|
|
12170
|
+
return new SootSimExpectation(el._matcher, findNode, getPage2, false);
|
|
12171
|
+
};
|
|
12172
|
+
}
|
|
12173
|
+
var SootSimExpectation = class _SootSimExpectation {
|
|
12174
|
+
matcher;
|
|
12175
|
+
findNode;
|
|
12176
|
+
getPage;
|
|
11392
12177
|
negated;
|
|
11393
12178
|
constructor(matcher, findNode, getPage2, negated) {
|
|
11394
12179
|
this.matcher = matcher;
|
|
@@ -11604,7 +12389,11 @@ var SootSimWaitForChain = class {
|
|
|
11604
12389
|
const node = await this.findNode(this.matcher);
|
|
11605
12390
|
const exists = node !== null && node !== void 0;
|
|
11606
12391
|
if (this._negated ? exists : !exists) {
|
|
11607
|
-
throw new Error(
|
|
12392
|
+
throw new Error(
|
|
12393
|
+
`waitFor toExist failed: ${JSON.stringify(this.matcher)}
|
|
12394
|
+
recent page diagnostics:
|
|
12395
|
+
${JSON.stringify(getSootsimNavigationDiagnostics(this.getPage()))}`
|
|
12396
|
+
);
|
|
11608
12397
|
}
|
|
11609
12398
|
};
|
|
11610
12399
|
return new SootSimWaitForAction(this.assertionFn, this.findNode, this.getPage);
|
|
@@ -11790,193 +12579,6 @@ var by = {
|
|
|
11790
12579
|
|
|
11791
12580
|
// detox/index.ts
|
|
11792
12581
|
var import_motion_change = __toESM(require_motion_change(), 1);
|
|
11793
|
-
|
|
11794
|
-
// detox/navigation-lifecycle.ts
|
|
11795
|
-
var import_attempt_events = __toESM(require_attempt_events(), 1);
|
|
11796
|
-
var DIAGNOSTIC_LIMIT = 40;
|
|
11797
|
-
var pageDiagnostics = /* @__PURE__ */ new WeakMap();
|
|
11798
|
-
var activeNavigations = /* @__PURE__ */ new WeakMap();
|
|
11799
|
-
var lastNavigations = /* @__PURE__ */ new WeakMap();
|
|
11800
|
-
var nextNavigationIdentity = 0;
|
|
11801
|
-
function recordPageDiagnostic(page, diagnostic, persist = false) {
|
|
11802
|
-
const entries = pageDiagnostics.get(page);
|
|
11803
|
-
if (!entries) return;
|
|
11804
|
-
entries.push(diagnostic);
|
|
11805
|
-
if (entries.length > DIAGNOSTIC_LIMIT) entries.shift();
|
|
11806
|
-
if (persist) (0, import_attempt_events.writeAttemptEvent)(diagnostic);
|
|
11807
|
-
}
|
|
11808
|
-
function isTopLevelDocumentRequest(page, request) {
|
|
11809
|
-
if (!request.isNavigationRequest() || request.resourceType() !== "document") {
|
|
11810
|
-
return false;
|
|
11811
|
-
}
|
|
11812
|
-
try {
|
|
11813
|
-
return request.frame() === page.mainFrame();
|
|
11814
|
-
} catch {
|
|
11815
|
-
return false;
|
|
11816
|
-
}
|
|
11817
|
-
}
|
|
11818
|
-
function recordNavigationMilestoneFor(page, active, milestone, details = {}) {
|
|
11819
|
-
recordPageDiagnostic(
|
|
11820
|
-
page,
|
|
11821
|
-
{
|
|
11822
|
-
...active,
|
|
11823
|
-
...details,
|
|
11824
|
-
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11825
|
-
milestone,
|
|
11826
|
-
target: process.env.CONFORMANCE_PROOF_TARGET || "sootsim",
|
|
11827
|
-
type: "rnx-navigation",
|
|
11828
|
-
url: details.url ?? active.navigationUrl
|
|
11829
|
-
},
|
|
11830
|
-
true
|
|
11831
|
-
);
|
|
11832
|
-
}
|
|
11833
|
-
function recordNavigationMilestone(page, milestone, details = {}) {
|
|
11834
|
-
const active = activeNavigations.get(page);
|
|
11835
|
-
if (active) recordNavigationMilestoneFor(page, active, milestone, details);
|
|
11836
|
-
}
|
|
11837
|
-
function attachPageDiagnostics(page) {
|
|
11838
|
-
if (pageDiagnostics.has(page)) return;
|
|
11839
|
-
pageDiagnostics.set(page, []);
|
|
11840
|
-
page.on("console", (message) => {
|
|
11841
|
-
recordPageDiagnostic(page, {
|
|
11842
|
-
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11843
|
-
level: message.type(),
|
|
11844
|
-
message: message.text(),
|
|
11845
|
-
type: "page-console"
|
|
11846
|
-
});
|
|
11847
|
-
});
|
|
11848
|
-
page.on("pageerror", (error) => {
|
|
11849
|
-
recordPageDiagnostic(page, {
|
|
11850
|
-
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11851
|
-
message: error.message,
|
|
11852
|
-
type: "page-error"
|
|
11853
|
-
});
|
|
11854
|
-
});
|
|
11855
|
-
page.on("request", (request) => {
|
|
11856
|
-
if (!isTopLevelDocumentRequest(page, request)) return;
|
|
11857
|
-
recordNavigationMilestone(page, "document-request", {
|
|
11858
|
-
method: request.method(),
|
|
11859
|
-
url: request.url()
|
|
11860
|
-
});
|
|
11861
|
-
});
|
|
11862
|
-
page.on("response", (response) => {
|
|
11863
|
-
const request = response.request();
|
|
11864
|
-
if (!isTopLevelDocumentRequest(page, request)) return;
|
|
11865
|
-
recordNavigationMilestone(page, "document-response", {
|
|
11866
|
-
headersReceived: true,
|
|
11867
|
-
status: response.status(),
|
|
11868
|
-
url: request.url()
|
|
11869
|
-
});
|
|
11870
|
-
});
|
|
11871
|
-
page.on("requestfinished", (request) => {
|
|
11872
|
-
if (!isTopLevelDocumentRequest(page, request)) return;
|
|
11873
|
-
recordNavigationMilestone(page, "document-request-finished", { url: request.url() });
|
|
11874
|
-
});
|
|
11875
|
-
page.on("requestfailed", (request) => {
|
|
11876
|
-
const failure = request.failure();
|
|
11877
|
-
const errorText = failure?.errorText ?? "";
|
|
11878
|
-
if (isTopLevelDocumentRequest(page, request)) {
|
|
11879
|
-
recordNavigationMilestone(page, "document-request-failed", {
|
|
11880
|
-
errorText,
|
|
11881
|
-
url: request.url()
|
|
11882
|
-
});
|
|
11883
|
-
return;
|
|
11884
|
-
}
|
|
11885
|
-
recordPageDiagnostic(page, {
|
|
11886
|
-
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11887
|
-
errorText,
|
|
11888
|
-
method: request.method(),
|
|
11889
|
-
type: "subresource-request-failed",
|
|
11890
|
-
url: request.url()
|
|
11891
|
-
});
|
|
11892
|
-
});
|
|
11893
|
-
page.on("domcontentloaded", () => {
|
|
11894
|
-
recordNavigationMilestone(page, "domcontentloaded");
|
|
11895
|
-
});
|
|
11896
|
-
page.on("load", () => {
|
|
11897
|
-
recordNavigationMilestone(page, "load");
|
|
11898
|
-
});
|
|
11899
|
-
}
|
|
11900
|
-
async function readSootsimPageState(page) {
|
|
11901
|
-
try {
|
|
11902
|
-
return await page.evaluate(() => {
|
|
11903
|
-
const bootMarks = Reflect.get(window, "__sootsimBootMarks");
|
|
11904
|
-
return {
|
|
11905
|
-
bodyText: document.body?.innerText?.slice(0, 500) ?? "",
|
|
11906
|
-
bootStage: document.documentElement.dataset.sootsimBootStage ?? null,
|
|
11907
|
-
bootMarks: Array.isArray(bootMarks) ? bootMarks.slice(-16) : [],
|
|
11908
|
-
capturedAtEpochMs: Date.now(),
|
|
11909
|
-
bridges: {
|
|
11910
|
-
sootsim: Boolean(window.SootSim),
|
|
11911
|
-
test: Boolean(window.__sootsimTest)
|
|
11912
|
-
},
|
|
11913
|
-
globals: Object.keys(window).filter((key) => key.startsWith("__sootsim") || key === "SootSim").sort(),
|
|
11914
|
-
readyState: document.readyState,
|
|
11915
|
-
title: document.title,
|
|
11916
|
-
url: window.location.href
|
|
11917
|
-
};
|
|
11918
|
-
});
|
|
11919
|
-
} catch (error) {
|
|
11920
|
-
return {
|
|
11921
|
-
evaluateError: error instanceof Error ? error.message : String(error)
|
|
11922
|
-
};
|
|
11923
|
-
}
|
|
11924
|
-
}
|
|
11925
|
-
async function describeSootsimBridgeFailure(page, cause, summary = "timed out waiting for sootsim test bridge", pageState) {
|
|
11926
|
-
const recordBridgeFailure = pageState === void 0;
|
|
11927
|
-
const state = pageState ?? await readSootsimPageState(page);
|
|
11928
|
-
const navigation = lastNavigations.get(page);
|
|
11929
|
-
if (recordBridgeFailure && navigation) {
|
|
11930
|
-
recordNavigationMilestoneFor(page, navigation, "error", {
|
|
11931
|
-
errorText: cause instanceof Error ? cause.message : String(cause),
|
|
11932
|
-
failurePhase: "bridge",
|
|
11933
|
-
pageState: state
|
|
11934
|
-
});
|
|
11935
|
-
}
|
|
11936
|
-
return new Error(
|
|
11937
|
-
[
|
|
11938
|
-
summary,
|
|
11939
|
-
`cause: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
11940
|
-
`page: ${JSON.stringify(state)}`,
|
|
11941
|
-
`recent page diagnostics:
|
|
11942
|
-
${JSON.stringify(getSootsimNavigationDiagnostics(page))}`
|
|
11943
|
-
].join("\n")
|
|
11944
|
-
);
|
|
11945
|
-
}
|
|
11946
|
-
async function navigateSootsimPage(page, url, identity) {
|
|
11947
|
-
attachPageDiagnostics(page);
|
|
11948
|
-
const navigation = {
|
|
11949
|
-
...identity,
|
|
11950
|
-
navigationUrl: url,
|
|
11951
|
-
navigationId: ++nextNavigationIdentity
|
|
11952
|
-
};
|
|
11953
|
-
activeNavigations.set(page, navigation);
|
|
11954
|
-
lastNavigations.set(page, navigation);
|
|
11955
|
-
recordNavigationMilestone(page, "start");
|
|
11956
|
-
try {
|
|
11957
|
-
return await page.goto(url, { waitUntil: "load", timeout: 3e4 });
|
|
11958
|
-
} catch (error) {
|
|
11959
|
-
const pageState = await readSootsimPageState(page);
|
|
11960
|
-
recordNavigationMilestone(page, "error", {
|
|
11961
|
-
errorText: error instanceof Error ? error.message : String(error),
|
|
11962
|
-
failurePhase: "navigation",
|
|
11963
|
-
pageState
|
|
11964
|
-
});
|
|
11965
|
-
throw await describeSootsimBridgeFailure(
|
|
11966
|
-
page,
|
|
11967
|
-
error,
|
|
11968
|
-
"sootsim navigation failed",
|
|
11969
|
-
pageState
|
|
11970
|
-
);
|
|
11971
|
-
} finally {
|
|
11972
|
-
activeNavigations.delete(page);
|
|
11973
|
-
}
|
|
11974
|
-
}
|
|
11975
|
-
function getSootsimNavigationDiagnostics(page) {
|
|
11976
|
-
return [...pageDiagnostics.get(page) ?? []];
|
|
11977
|
-
}
|
|
11978
|
-
|
|
11979
|
-
// detox/index.ts
|
|
11980
12582
|
var import_proof_frame = __toESM(require_proof_frame(), 1);
|
|
11981
12583
|
var BASE_URL = process.env.PEACH_URL || "http://localhost:5173";
|
|
11982
12584
|
var SCREENSHOT_DIR = process.env.PEACH_SCREENSHOT_DIR || path2.join(process.cwd(), "test", "detox-driver", "screenshots", String(process.pid));
|
|
@@ -12174,6 +12776,8 @@ async function waitForSootsimWorkletsIdle(page, timeout = 3e3) {
|
|
|
12174
12776
|
const deadline = start + timeout2;
|
|
12175
12777
|
const requiredStableMs = 120;
|
|
12176
12778
|
let lastPending = null;
|
|
12779
|
+
let completedReads = 0;
|
|
12780
|
+
let lastReply = null;
|
|
12177
12781
|
while (Date.now() < deadline) {
|
|
12178
12782
|
let timer;
|
|
12179
12783
|
const stats = await Promise.race([
|
|
@@ -12189,6 +12793,8 @@ async function waitForSootsimWorkletsIdle(page, timeout = 3e3) {
|
|
|
12189
12793
|
});
|
|
12190
12794
|
if (stats === void 0) break;
|
|
12191
12795
|
if (stats === null) return { settled: true, elapsed: Date.now() - start };
|
|
12796
|
+
completedReads++;
|
|
12797
|
+
lastReply = JSON.stringify({ elapsedMs: Date.now() - start, stats });
|
|
12192
12798
|
lastPending = stats.pendingRunWorklets;
|
|
12193
12799
|
if (lastPending === 0 && stats.runWorkletsIdleMs !== null && stats.runWorkletsIdleMs >= requiredStableMs) {
|
|
12194
12800
|
return {
|
|
@@ -12199,30 +12805,69 @@ async function waitForSootsimWorkletsIdle(page, timeout = 3e3) {
|
|
|
12199
12805
|
}
|
|
12200
12806
|
await sleep(25);
|
|
12201
12807
|
}
|
|
12202
|
-
|
|
12808
|
+
const waited = Date.now() - start;
|
|
12809
|
+
const observation = { completedReads, lastReply };
|
|
12810
|
+
let realms = null;
|
|
12203
12811
|
if (lastPending === null) {
|
|
12204
|
-
const
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
)
|
|
12210
|
-
|
|
12211
|
-
|
|
12812
|
+
const probe = async (bridge) => {
|
|
12813
|
+
if (!bridge || typeof bridge !== "object" || !("callTestBridge" in bridge) || typeof bridge.callTestBridge !== "function") {
|
|
12814
|
+
return { status: "missing-bridge" };
|
|
12815
|
+
}
|
|
12816
|
+
const callTestBridge = bridge.callTestBridge.bind(bridge);
|
|
12817
|
+
const asked = Date.now();
|
|
12818
|
+
let timer;
|
|
12819
|
+
try {
|
|
12820
|
+
return await Promise.race([
|
|
12821
|
+
Promise.resolve().then(() => callTestBridge("getPeerStats", false)).then(
|
|
12822
|
+
(stats) => ({
|
|
12823
|
+
status: "answered",
|
|
12824
|
+
elapsedMs: Date.now() - asked,
|
|
12825
|
+
stats
|
|
12826
|
+
}),
|
|
12827
|
+
(error) => ({
|
|
12828
|
+
status: "rejected",
|
|
12829
|
+
elapsedMs: Date.now() - asked,
|
|
12830
|
+
error: error instanceof Error ? error.message : String(error)
|
|
12831
|
+
})
|
|
12832
|
+
),
|
|
12833
|
+
new Promise((resolve3) => {
|
|
12834
|
+
timer = setTimeout(
|
|
12835
|
+
() => resolve3({ status: "no-reply", elapsedMs: Date.now() - asked }),
|
|
12836
|
+
1e3
|
|
12837
|
+
);
|
|
12838
|
+
})
|
|
12839
|
+
]);
|
|
12840
|
+
} finally {
|
|
12841
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
12842
|
+
}
|
|
12843
|
+
};
|
|
12844
|
+
const timerAsked = Date.now();
|
|
12845
|
+
const [tenant, shell, pageTimerLateMs] = await Promise.all([
|
|
12846
|
+
probe(window.__sootsimRenderHost),
|
|
12847
|
+
probe(window.SootSim?.bridges?.shellHost),
|
|
12848
|
+
sleep(0).then(() => Date.now() - timerAsked)
|
|
12849
|
+
]);
|
|
12850
|
+
realms = JSON.stringify({
|
|
12851
|
+
phase: "after-deadline",
|
|
12852
|
+
tenant,
|
|
12853
|
+
shell,
|
|
12854
|
+
pageTimerLateMs
|
|
12855
|
+
});
|
|
12212
12856
|
}
|
|
12213
12857
|
return {
|
|
12214
12858
|
settled: false,
|
|
12215
|
-
elapsed:
|
|
12859
|
+
elapsed: waited,
|
|
12216
12860
|
pending: lastPending,
|
|
12217
|
-
|
|
12861
|
+
realms,
|
|
12862
|
+
observation
|
|
12218
12863
|
};
|
|
12219
12864
|
},
|
|
12220
12865
|
{ timeout }
|
|
12221
12866
|
);
|
|
12222
12867
|
if (!result?.settled) {
|
|
12223
|
-
const pending = result?.pending ?? `no peer stats reply;
|
|
12868
|
+
const pending = result?.pending ?? `no peer stats reply; ${result?.realms}`;
|
|
12224
12869
|
throw new Error(
|
|
12225
|
-
`sootsim worklet runtime did not settle after ${result?.elapsed ?? timeout}ms (pending=${pending})`
|
|
12870
|
+
`sootsim worklet runtime did not settle after ${result?.elapsed ?? timeout}ms (pending=${pending}; observation=${JSON.stringify(result?.observation)})`
|
|
12226
12871
|
);
|
|
12227
12872
|
}
|
|
12228
12873
|
}
|
|
@@ -12461,41 +13106,49 @@ async function nodeOffsetToPage(page, nodeInfo, dx, dy) {
|
|
|
12461
13106
|
const center = getNodeCenter(nodeInfo);
|
|
12462
13107
|
return sootsimToPage(page, center.x + dx, center.y + dy);
|
|
12463
13108
|
}
|
|
12464
|
-
async function
|
|
12465
|
-
const resolvedTarget = await page.evaluate(
|
|
12466
|
-
(nodeId) => window.__sootsimTest?.resolveTapTarget?.(nodeId) ?? null,
|
|
12467
|
-
nodeInfo.nodeId
|
|
12468
|
-
);
|
|
12469
|
-
const center = resolvedTarget && typeof resolvedTarget.cx === "number" && typeof resolvedTarget.cy === "number" ? { x: resolvedTarget.cx, y: resolvedTarget.cy } : getNodeCenter(nodeInfo);
|
|
12470
|
-
const frame = nodeInfo.visibleFrame ?? {
|
|
12471
|
-
x: nodeInfo.absolutePosition?.x ?? nodeInfo.layout?.x ?? 0,
|
|
12472
|
-
y: nodeInfo.absolutePosition?.y ?? nodeInfo.layout?.y ?? 0,
|
|
12473
|
-
width: nodeInfo.layout?.width ?? 0,
|
|
12474
|
-
height: nodeInfo.layout?.height ?? 0
|
|
12475
|
-
};
|
|
12476
|
-
const viewport = await readSootsimInteractiveViewport(page);
|
|
12477
|
-
const fullFrameTolerance = 0.5;
|
|
12478
|
-
const canTapCenter = typeof nodeInfo.absolutePosition?.x === "number" && typeof nodeInfo.absolutePosition?.y === "number" && typeof nodeInfo.layout?.width === "number" && typeof nodeInfo.layout?.height === "number" && Math.abs(frame.x - nodeInfo.absolutePosition.x) <= fullFrameTolerance && Math.abs(frame.y - nodeInfo.absolutePosition.y) <= fullFrameTolerance && frame.width >= nodeInfo.layout.width - fullFrameTolerance && frame.height >= nodeInfo.layout.height - fullFrameTolerance && center.x >= 0 && center.y >= 0 && center.x < viewport.width && center.y < viewport.height;
|
|
12479
|
-
if (canTapCenter) return center;
|
|
12480
|
-
const left = Math.max(0, frame.x);
|
|
12481
|
-
const top = Math.max(0, frame.y);
|
|
12482
|
-
const right = Math.min(viewport.width, frame.x + frame.width);
|
|
12483
|
-
const bottom = Math.min(viewport.height, frame.y + frame.height);
|
|
12484
|
-
if (right <= left || bottom <= top) {
|
|
12485
|
-
return center;
|
|
12486
|
-
}
|
|
12487
|
-
return {
|
|
12488
|
-
x: left + (right - left) / 2,
|
|
12489
|
-
y: top + (bottom - top) / 2
|
|
12490
|
-
};
|
|
12491
|
-
}
|
|
12492
|
-
async function dispatchTapAtSootsimPoint(page, x, y, token) {
|
|
13109
|
+
async function dispatchTapAtSootsimPoint(page, point, token) {
|
|
12493
13110
|
await page.evaluate(
|
|
12494
|
-
async ({
|
|
13111
|
+
async ({ point: point2, token: token2 }) => {
|
|
13112
|
+
let x;
|
|
13113
|
+
let y;
|
|
13114
|
+
if ("nodeId" in point2) {
|
|
13115
|
+
const resolved = await window.__sootsimTest.resolveTapTarget(point2.nodeId);
|
|
13116
|
+
if (!resolved) throw new Error(`element disappeared before tap: ${point2.nodeId}`);
|
|
13117
|
+
const node = resolved.match;
|
|
13118
|
+
if (point2.offset) {
|
|
13119
|
+
x = node.absolutePosition.x + (point2.offset.x ?? node.layout.width / 2);
|
|
13120
|
+
y = node.absolutePosition.y + (point2.offset.y ?? node.layout.height / 2);
|
|
13121
|
+
} else {
|
|
13122
|
+
x = resolved.cx;
|
|
13123
|
+
y = resolved.cy;
|
|
13124
|
+
const frame = node.visibleFrame ?? {
|
|
13125
|
+
x: node.absolutePosition.x,
|
|
13126
|
+
y: node.absolutePosition.y,
|
|
13127
|
+
width: node.layout.width,
|
|
13128
|
+
height: node.layout.height
|
|
13129
|
+
};
|
|
13130
|
+
const { viewport } = point2;
|
|
13131
|
+
const tolerance = 0.5;
|
|
13132
|
+
const canTapCenter = Math.abs(frame.x - node.absolutePosition.x) <= tolerance && Math.abs(frame.y - node.absolutePosition.y) <= tolerance && frame.width >= node.layout.width - tolerance && frame.height >= node.layout.height - tolerance && x >= 0 && y >= 0 && x < viewport.width && y < viewport.height;
|
|
13133
|
+
if (!canTapCenter) {
|
|
13134
|
+
const left = Math.max(0, frame.x);
|
|
13135
|
+
const top = Math.max(0, frame.y);
|
|
13136
|
+
const right = Math.min(viewport.width, frame.x + frame.width);
|
|
13137
|
+
const bottom = Math.min(viewport.height, frame.y + frame.height);
|
|
13138
|
+
if (right > left && bottom > top) {
|
|
13139
|
+
x = left + (right - left) / 2;
|
|
13140
|
+
y = top + (bottom - top) / 2;
|
|
13141
|
+
}
|
|
13142
|
+
}
|
|
13143
|
+
}
|
|
13144
|
+
} else {
|
|
13145
|
+
;
|
|
13146
|
+
({ x, y } = point2);
|
|
13147
|
+
}
|
|
12495
13148
|
const interactTap = window.SootSim?.bridges?.interact?.tap;
|
|
12496
13149
|
if (typeof interactTap === "function") {
|
|
12497
13150
|
if (token2) window.__sootsimAnchorTimedInput?.(token2);
|
|
12498
|
-
const result = await interactTap(
|
|
13151
|
+
const result = await interactTap(x, y);
|
|
12499
13152
|
if (result && (typeof result !== "object" || result.hit !== false)) {
|
|
12500
13153
|
return;
|
|
12501
13154
|
}
|
|
@@ -12505,9 +13158,9 @@ async function dispatchTapAtSootsimPoint(page, x, y, token) {
|
|
|
12505
13158
|
throw new Error("sootsim tap bridge is not installed");
|
|
12506
13159
|
}
|
|
12507
13160
|
if (token2) window.__sootsimAnchorTimedInput?.(token2);
|
|
12508
|
-
await tap(
|
|
13161
|
+
await tap(x, y);
|
|
12509
13162
|
},
|
|
12510
|
-
{
|
|
13163
|
+
{ point, token }
|
|
12511
13164
|
);
|
|
12512
13165
|
}
|
|
12513
13166
|
async function focusElementForTextEntry(el) {
|
|
@@ -12696,11 +13349,13 @@ function createSootSimElement(matcher) {
|
|
|
12696
13349
|
`Cannot perform action due to constraint failure: element not visible (${describeNodeVisibility(node)}): ${JSON.stringify(matcher)}`
|
|
12697
13350
|
);
|
|
12698
13351
|
}
|
|
12699
|
-
const
|
|
12700
|
-
const targetSootSimX = typeof point?.x === "number" ? node.absolutePosition.x + point.x : defaultPoint?.x ?? node.absolutePosition.x + node.layout.width / 2;
|
|
12701
|
-
const targetSootSimY = typeof point?.y === "number" ? node.absolutePosition.y + point.y : defaultPoint?.y ?? node.absolutePosition.y + node.layout.height / 2;
|
|
13352
|
+
const viewport = await readSootsimInteractiveViewport(page);
|
|
12702
13353
|
const captureToken = page.__sootsimCaptureToken;
|
|
12703
|
-
await dispatchTapAtSootsimPoint(
|
|
13354
|
+
await dispatchTapAtSootsimPoint(
|
|
13355
|
+
page,
|
|
13356
|
+
{ nodeId: node.nodeId, viewport, offset: point },
|
|
13357
|
+
captureToken
|
|
13358
|
+
);
|
|
12704
13359
|
if (_synchronizationEnabled) {
|
|
12705
13360
|
await waitForSootsimIdle2(page);
|
|
12706
13361
|
}
|
|
@@ -13014,8 +13669,10 @@ function createSootSimElement(matcher) {
|
|
|
13014
13669
|
const captureToken = page.__sootsimCaptureToken;
|
|
13015
13670
|
await dispatchTapAtSootsimPoint(
|
|
13016
13671
|
page,
|
|
13017
|
-
|
|
13018
|
-
|
|
13672
|
+
{
|
|
13673
|
+
x: tapTarget.target.absolutePosition.x + tapTarget.target.layout.width / 2,
|
|
13674
|
+
y: tapTarget.target.absolutePosition.y + tapTarget.target.layout.height / 2
|
|
13675
|
+
},
|
|
13019
13676
|
captureToken
|
|
13020
13677
|
);
|
|
13021
13678
|
},
|
|
@@ -13249,7 +13906,7 @@ var device = {
|
|
|
13249
13906
|
"cli.js"
|
|
13250
13907
|
);
|
|
13251
13908
|
try {
|
|
13252
|
-
await (0, import_node_util.promisify)(
|
|
13909
|
+
await (0, import_node_util.promisify)(import_node_child_process4.execFile)(
|
|
13253
13910
|
process.execPath,
|
|
13254
13911
|
[cliPath, "install", "chromium"],
|
|
13255
13912
|
{
|