peachsim 0.1.1620 → 0.1.1635
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/LICENSE +1 -1
- package/README.md +45 -6
- package/cli/app-config.ts +4 -1
- package/cli/app-fonts.ts +39 -18
- package/cli/app-stubs.ts +224 -9
- package/cli/bridge-flow-runner.ts +248 -156
- package/cli/cloud-client.ts +68 -57
- package/cli/command-registry.ts +1 -0
- package/cli/commands/box/search-command.ts +3 -2
- package/cli/commands/box.ts +10 -29
- package/cli/commands/control.ts +391 -92
- package/cli/commands/doctor.ts +17 -184
- package/cli/commands/flow.ts +79 -11
- package/cli/commands/inspect/core.ts +10 -5
- package/cli/commands/inspect/settling.ts +71 -22
- package/cli/commands/inspect/wait-ready.ts +12 -0
- package/cli/commands/inspect.ts +26 -3
- package/cli/commands/install-desktop.ts +1 -0
- package/cli/commands/maestro-compare.ts +105 -67
- package/cli/commands/maestro.ts +9 -1
- package/cli/commands/platform.ts +71 -36
- package/cli/commands/record.ts +21 -1
- package/cli/commands/screenshot.ts +23 -1
- package/cli/commands/serve.ts +7 -2
- package/cli/commands/setup.ts +19 -42
- package/cli/commands/swift.ts +5 -0
- package/cli/commands/upload.ts +51 -8
- package/cli/desktop-companion.ts +102 -17
- package/cli/dev-build-freshness.ts +37 -2
- package/cli/drivers/desktop.ts +14 -1
- package/cli/drivers/playwright-sim-host.ts +44 -8
- package/cli/drivers/playwright.ts +9 -8
- package/cli/drivers/types.ts +5 -0
- package/cli/maestro-accessibility.ts +53 -0
- package/cli/maestro-compare.ts +108 -12
- package/cli/main.ts +2 -1
- package/cli/outbound-endpoints.ts +35 -6
- package/cli/parent-pid.ts +0 -9
- package/cli/pause-aware-timeout.ts +102 -0
- package/cli/remote-simulators.ts +112 -0
- package/cli/remoteSimulatorContract.ts +21 -0
- package/cli/scene-video.ts +89 -0
- package/cli/ws-bridge.ts +23 -14
- package/detox/attempt-events.cjs +4 -0
- package/detox/expectations.ts +5 -1
- package/detox/index.ts +241 -181
- package/detox/motion-change.cjs +73 -0
- package/detox/motion-change.d.cts +21 -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 +13 -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 +14 -8
- package/dist-lib/bridge-contract.mjs +13 -7
- package/dist-lib/bundle-channel.cjs +10480 -7962
- 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 +10 -6
- package/dist-lib/config.mjs +10 -6
- package/dist-lib/detox/index.cjs +1854 -966
- package/dist-lib/dev-bundle-resolution.cjs +64 -24
- package/dist-lib/expo-swift-bundle.cjs +8715 -6271
- package/dist-lib/expo-swift-metadata.cjs +7 -4
- package/dist-lib/expo-swift-metadata.mjs +7 -4
- package/dist-lib/home-paths.cjs +32 -3
- package/dist-lib/host/bridge-host.cjs +10135 -7060
- 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 +1843 -408
- 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 +1182 -418
- package/dist-lib/native-app-identity-project.cjs +782 -23
- package/dist-lib/native-app-identity-project.mjs +781 -23
- package/dist-lib/native-app-identity.cjs +276 -9
- package/dist-lib/native-app-identity.mjs +273 -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 +8 -1
- package/dist-lib/react-native-host-modules.mjs +8 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +106 -28
- package/dist-lib/sdk.cjs +115 -34
- package/dist-lib/sdk.mjs +115 -33
- package/dist-lib/skills.cjs +15274 -9904
- package/dist-lib/swift-compile.cjs +1165 -173
- package/dist-lib/swift-compile.mjs +1212 -203
- package/dist-lib/swift-package.cjs +12 -3
- package/dist-lib/swift-package.mjs +12 -3
- package/dist-lib/swift-submit.cjs +7 -1
- package/dist-lib/swift-submit.mjs +5 -1
- package/dist-lib/swift-toolchain.cjs +133 -18
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +2648 -862
- package/dist-lib/vite.cjs +70 -14
- package/dist-lib/worklet-executable.cjs +25 -2
- package/dist-lib/worklet-executable.mjs +25 -2
- package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
- package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
- package/package.json +2 -2
- package/scripts/dev-server-scanner.ts +35 -14
- package/skills/peach-perf/SKILL.md +11 -5
- package/skills/peach-setup/SKILL.md +16 -19
- 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/bridge-constants.ts +11 -0
- package/src/bridge-contract.ts +22 -34
- package/src/bundleGlobalFooter.ts +26 -7
- package/src/codex-client.ts +3 -2
- package/src/config.ts +15 -0
- package/src/desktop-host-delivery.ts +5 -1
- package/src/dev-bundle-resolution.ts +60 -26
- package/src/expo-kotlin-host.ts +6 -36
- package/src/expo-manifest-body.ts +13 -0
- package/src/expo-swift-bundle.ts +17 -12
- package/src/expo-swift-host.ts +640 -192
- package/src/expo-swift-ready.ts +78 -0
- package/src/expoSwiftContract.ts +19 -0
- package/src/home-paths.ts +48 -2
- package/src/host/bridge-host.ts +12 -57
- 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 +142 -5
- package/src/native-app-identity.ts +176 -11
- package/src/native-firebase-config.ts +209 -13
- package/src/nitro-compile.ts +2 -5
- package/src/nitro-source.ts +147 -63
- package/src/process-group.ts +114 -61
- package/src/process-output.ts +0 -9
- package/src/public-brand.ts +1 -0
- package/src/react-native-bridge-modules.ts +416 -0
- package/src/react-native-host-modules.ts +7 -0
- package/src/sim-client.ts +6 -4
- package/src/swift-binary-modules.ts +2 -2
- package/src/swift-compile.ts +1007 -108
- package/src/swift-compiler-digest.ts +14 -0
- package/src/swift-distribution.lock.json +40 -12
- package/src/swift-distribution.ts +61 -9
- package/src/swift-host.ts +149 -56
- package/src/swift-icu.ts +14 -6
- package/src/swift-objc-sdk.ts +133 -10
- package/src/swift-objc-standin.ts +38 -3
- package/src/swift-package-manifest.ts +21 -6
- package/src/swift-package.ts +15 -1
- package/src/swift-packages.ts +119 -60
- package/src/swift-standin-emit.ts +57 -9
- package/src/swift-standins.ts +185 -25
- package/src/swift-submit.ts +10 -0
- package/src/swift-toolchain.ts +149 -23
- package/src/vite-plugin.ts +20 -20
- package/src/worklet-executable.ts +30 -3
- package/src/worklets-babel.ts +35 -14
- package/src/xcode-project.ts +10 -0
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -6,14 +6,20 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
6
6
|
// src/bridge-contract.ts
|
|
7
7
|
var SEMANTIC_READY_CONTENT_NODE_FLOOR = 100;
|
|
8
8
|
var HEADLESS_TENANT_FETCH_HUNG_MARKER = "headless tenant fetch hung";
|
|
9
|
-
function
|
|
10
|
-
|
|
9
|
+
function readyProbeContentBasis(probe) {
|
|
10
|
+
if (probe.paintedAppContent === true) return "paintedAppContent";
|
|
11
|
+
if ((probe.browserSurfaceCount ?? 0) > 0) return "browserSurface";
|
|
12
|
+
if (probe.liveFrameActive) return "liveFrame";
|
|
13
|
+
if (probe.targets > 0) return "targets";
|
|
14
|
+
if (probe.flag === true && probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR)
|
|
15
|
+
return "nodeFloor";
|
|
16
|
+
return "";
|
|
11
17
|
}
|
|
12
|
-
function
|
|
13
|
-
return probe
|
|
18
|
+
function readyProbeHasContent(probe) {
|
|
19
|
+
return readyProbeContentBasis({ ...probe, flag: true }) !== "";
|
|
14
20
|
}
|
|
15
21
|
function readyProbeIsReady(probe) {
|
|
16
|
-
return (probe
|
|
22
|
+
return readyProbeContentBasis(probe) !== "" && probe.externalReady !== false && !probe.externalError && !probe.loadingText;
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
// src/bridge-contract-input.ts
|
|
@@ -863,7 +869,10 @@ function waitReadyStatus(result, ready) {
|
|
|
863
869
|
externalError: probe?.externalError ?? "",
|
|
864
870
|
suppressedEntryError: probe?.suppressedEntryError ?? "",
|
|
865
871
|
errors: probe?.errors ?? 0,
|
|
866
|
-
bridgeError: result.error ?? ""
|
|
872
|
+
bridgeError: result.error ?? "",
|
|
873
|
+
paintedAppContent: probe?.paintedAppContent ?? false,
|
|
874
|
+
treeQuietMs: probe?.treeQuietMs ?? 0,
|
|
875
|
+
readyBasis: probe ? readyProbeContentBasis(probe) : ""
|
|
867
876
|
};
|
|
868
877
|
}
|
|
869
878
|
async function inspectWaitSelector(bridge, testId, timeoutMs = 5e3, opts = {}) {
|
|
@@ -1479,6 +1488,28 @@ async function resolveTargetCoords(bridge, target) {
|
|
|
1479
1488
|
};
|
|
1480
1489
|
}
|
|
1481
1490
|
|
|
1491
|
+
// cli/maestro-accessibility.ts
|
|
1492
|
+
function accessibilityBounds(node) {
|
|
1493
|
+
const left = Math.trunc(node.frame.x);
|
|
1494
|
+
const top = Math.trunc(node.frame.y);
|
|
1495
|
+
return {
|
|
1496
|
+
x: left,
|
|
1497
|
+
y: top,
|
|
1498
|
+
width: Math.trunc(node.frame.x + node.frame.width) - left,
|
|
1499
|
+
height: Math.trunc(node.frame.y + node.frame.height) - top
|
|
1500
|
+
};
|
|
1501
|
+
}
|
|
1502
|
+
function sameNativeAccessibilityShape(a, b, bounds) {
|
|
1503
|
+
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) {
|
|
1504
|
+
return false;
|
|
1505
|
+
}
|
|
1506
|
+
for (const [index, child] of a.children.entries()) {
|
|
1507
|
+
const other = b.children[index];
|
|
1508
|
+
if (!other || !sameNativeAccessibilityShape(child, other, bounds)) return false;
|
|
1509
|
+
}
|
|
1510
|
+
return true;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1482
1513
|
// cli/commands/inspect/settling.ts
|
|
1483
1514
|
var RuntimeReadinessUnsupportedError = class extends Error {
|
|
1484
1515
|
constructor(runtimeVersion, missingFields) {
|
|
@@ -1511,6 +1542,7 @@ async function waitForSootsimIdle({
|
|
|
1511
1542
|
stablePolls = 3,
|
|
1512
1543
|
strict = false,
|
|
1513
1544
|
paintStill = false,
|
|
1545
|
+
maestro = false,
|
|
1514
1546
|
motionOnly = false,
|
|
1515
1547
|
transitionStartWindowMs = 80,
|
|
1516
1548
|
transitionTimeoutMs = 4e3
|
|
@@ -1542,12 +1574,15 @@ async function waitForSootsimIdle({
|
|
|
1542
1574
|
const pollMs = ${Math.max(1, Math.round(pollMs))}
|
|
1543
1575
|
const strict = ${strict ? "true" : "false"}
|
|
1544
1576
|
const paintStill = ${paintStill ? "true" : "false"}
|
|
1577
|
+
const maestro = ${maestro ? "true" : "false"}
|
|
1578
|
+
const accessibilityBounds = ${accessibilityBounds.toString()}
|
|
1579
|
+
const sameNativeAccessibilityShape = ${sameNativeAccessibilityShape.toString()}
|
|
1545
1580
|
const motionOnly = ${motionOnly ? "true" : "false"}
|
|
1546
1581
|
// full mounted-geometry observation needs at least two hierarchy reads
|
|
1547
1582
|
// plus the stillness window, which a sub-second budget cannot afford:
|
|
1548
1583
|
// tight budgets (auto-wait) settle on worker stillness plus root
|
|
1549
1584
|
// membership, generous ones confirm the geometry too.
|
|
1550
|
-
const fullGeometry = ${!motionOnly && maxMs >= 1e3 ? "true" : "false"}
|
|
1585
|
+
const fullGeometry = ${!maestro && !motionOnly && maxMs >= 1e3 ? "true" : "false"}
|
|
1551
1586
|
const requiredStillMs = paintStill ? 0 : ${Math.max(1, Math.round(stablePolls)) * Math.max(1, Math.round(pollMs))}
|
|
1552
1587
|
const minimumStablePolls = paintStill ? 1 : ${Math.min(2, Math.max(1, Math.round(stablePolls)))}
|
|
1553
1588
|
const composite = paintStill ? window.SootSim?.bridges?.liveComposite : null
|
|
@@ -1669,6 +1704,9 @@ async function waitForSootsimIdle({
|
|
|
1669
1704
|
// strict also waits out shell motion: a system alert, sheet or menu
|
|
1670
1705
|
// animates in the shell worker while the app's own stats read still,
|
|
1671
1706
|
// so its presentation is complete only once the shell's list empties.
|
|
1707
|
+
const accessibilityRead = maestro
|
|
1708
|
+
? answer(() => window.__sootsimTest.captureAccessibilityTree()).catch(() => null)
|
|
1709
|
+
: null
|
|
1672
1710
|
const motionRead = strict
|
|
1673
1711
|
? answer(() => window.__sootsimTest?.listAnimations?.()).catch(() => null)
|
|
1674
1712
|
: null
|
|
@@ -1678,9 +1716,12 @@ async function waitForSootsimIdle({
|
|
|
1678
1716
|
// the compositor rejects a stats request it is too busy to answer.
|
|
1679
1717
|
const compositorRead = answer(() => window.__sootsimCompositor.getStats()).catch(() => BUSY)
|
|
1680
1718
|
const countsRead = motionOnly ? null : answer(() => window.__sootsimTest?.getRequestCounts?.()).catch(() => null)
|
|
1681
|
-
// mounted-root membership: the
|
|
1682
|
-
// mounts, unmounts or recycles, in
|
|
1683
|
-
|
|
1719
|
+
// mounted-root membership: the count of nodes that can reach the
|
|
1720
|
+
// window moves while the screen mounts, unmounts or recycles, in
|
|
1721
|
+
// either render mode. a screen a pushed one covers or an inactive
|
|
1722
|
+
// tab stays mounted out of the window, so what it mounts is not
|
|
1723
|
+
// screen motion.
|
|
1724
|
+
const nodeCountRead = answer(() => window.__sootsimTest?.getWindowNodeCount?.()).catch(() => null)
|
|
1684
1725
|
// the mounted hierarchy in render-worker mode comes from the test
|
|
1685
1726
|
// bridge: window.__sootsimRoot is an empty placeholder there, so a
|
|
1686
1727
|
// walk over it hashes every screen to the same empty string while
|
|
@@ -1710,7 +1751,7 @@ async function waitForSootsimIdle({
|
|
|
1710
1751
|
const motion = await motionRead
|
|
1711
1752
|
if (motion === BUSY) workerBusy = true
|
|
1712
1753
|
else if (Array.isArray(motion)) {
|
|
1713
|
-
const blocking = motion.filter((anim) => anim.realm === 'shell' && anim.priority !== 'low')
|
|
1754
|
+
const blocking = motion.filter((anim) => anim.realm === 'shell' && anim.priority !== 'low' && anim.visible !== false)
|
|
1714
1755
|
shellAnimating = blocking.length > 0
|
|
1715
1756
|
// name what holds the settle so a timeout points at its owner.
|
|
1716
1757
|
shellBlockers = blocking
|
|
@@ -1742,6 +1783,8 @@ async function waitForSootsimIdle({
|
|
|
1742
1783
|
stats.hasActiveAnims === true ||
|
|
1743
1784
|
stats.hasActiveBlockingNativeAnimations === true ||
|
|
1744
1785
|
(!paintStill && stats.hasPendingBlockingAnimationFrames === true)
|
|
1786
|
+
// the runtime reports only layout work that can reach the window:
|
|
1787
|
+
// a covered screen or inactive tab committing does not hold it.
|
|
1745
1788
|
layoutDirty =
|
|
1746
1789
|
stats.layoutDirty === true && stats.renderRequested === true
|
|
1747
1790
|
// a freshly-pushed screen showing a skeleton is layout-stable
|
|
@@ -1774,6 +1817,11 @@ async function waitForSootsimIdle({
|
|
|
1774
1817
|
const total = await nodeCountRead
|
|
1775
1818
|
if (total === BUSY) workerBusy = true
|
|
1776
1819
|
nodeCount = typeof total === 'number' ? total : null
|
|
1820
|
+
const accessibility = accessibilityRead ? await accessibilityRead : null
|
|
1821
|
+
const nativeHierarchy = Array.isArray(accessibility) && accessibility.length > 0
|
|
1822
|
+
? accessibility
|
|
1823
|
+
: null
|
|
1824
|
+
if (accessibility === BUSY) workerBusy = true
|
|
1777
1825
|
let hierarchy = hierarchyRead ? await hierarchyRead : null
|
|
1778
1826
|
if (hierarchy === BUSY) {
|
|
1779
1827
|
workerBusy = true
|
|
@@ -1833,9 +1881,15 @@ async function waitForSootsimIdle({
|
|
|
1833
1881
|
webViewStarting = true
|
|
1834
1882
|
webViewBlocker = 'preview progress element displayed'
|
|
1835
1883
|
} else {
|
|
1836
|
-
|
|
1884
|
+
// a loading document with no area (an app's hidden worker or
|
|
1885
|
+
// executor frame) paints nothing, and a screenshot on device
|
|
1886
|
+
// does not wait for it.
|
|
1887
|
+
const unreadyWebView = [...document.querySelectorAll(
|
|
1837
1888
|
'[data-sootsim-webview-loading="true"], [data-sootsim-webview-mode="placeholder"]'
|
|
1838
|
-
)
|
|
1889
|
+
)].find((view) => {
|
|
1890
|
+
const frame = view.querySelector('iframe')
|
|
1891
|
+
return !frame || frame.clientWidth > 0 || frame.clientHeight > 0
|
|
1892
|
+
})
|
|
1839
1893
|
if (unreadyWebView) {
|
|
1840
1894
|
webViewStarting = true
|
|
1841
1895
|
webViewBlocker = 'webView document still loading'
|
|
@@ -1854,7 +1908,7 @@ async function waitForSootsimIdle({
|
|
|
1854
1908
|
pixelFrameToken = token
|
|
1855
1909
|
}
|
|
1856
1910
|
}
|
|
1857
|
-
return { layout: nodes.join(';'), screenPixels, animating, shellAnimating, shellBlockers, layoutDirty, pendingFetches, workerBusy, webViewStarting, webViewBlocker, renderStatsAvailable, requestTotal, requestInFlight, appCommits, nodeCount }
|
|
1911
|
+
return { layout: nodes.join(';'), nativeHierarchy, screenPixels, animating, shellAnimating, shellBlockers, layoutDirty, pendingFetches, workerBusy, webViewStarting, webViewBlocker, renderStatsAvailable, requestTotal, requestInFlight, appCommits, nodeCount }
|
|
1858
1912
|
}
|
|
1859
1913
|
|
|
1860
1914
|
// how long generic background network is allowed to keep us waiting AFTER
|
|
@@ -1868,6 +1922,7 @@ async function waitForSootsimIdle({
|
|
|
1868
1922
|
// so the generic request counters are a courtesy, not a gate: honor them
|
|
1869
1923
|
// only within this grace once the screen is visually still.
|
|
1870
1924
|
const networkQuietGraceMs = 1200
|
|
1925
|
+
let lastNativeHierarchy = null
|
|
1871
1926
|
let lastLayout = ''
|
|
1872
1927
|
let lastScreenPixels = null
|
|
1873
1928
|
let screenChangedPolls = 0
|
|
@@ -1895,6 +1950,9 @@ async function waitForSootsimIdle({
|
|
|
1895
1950
|
}
|
|
1896
1951
|
return true
|
|
1897
1952
|
}
|
|
1953
|
+
const hierarchyUnchanged = (current, previous) =>
|
|
1954
|
+
current !== null && previous !== null && current.length === previous.length &&
|
|
1955
|
+
current.every((node, index) => sameNativeAccessibilityShape(node, previous[index], accessibilityBounds))
|
|
1898
1956
|
const IDLE_HELD = { idleHeld: true }
|
|
1899
1957
|
while (true) {
|
|
1900
1958
|
if (clockNow() >= deadline) {
|
|
@@ -1940,7 +1998,7 @@ async function waitForSootsimIdle({
|
|
|
1940
1998
|
// the loop head drains a transition still in flight before it ends.
|
|
1941
1999
|
if (snapshot.workerBusy && clockNow() >= deadline && report) continue
|
|
1942
2000
|
polls++
|
|
1943
|
-
report = { snapshot, layout: lastLayout, screenPixels: lastScreenPixels, requestTotal: lastRequestTotal, appCommits: lastAppCommits, nodeCount: lastNodeCount }
|
|
2001
|
+
report = { snapshot, nativeHierarchy: lastNativeHierarchy, layout: lastLayout, screenPixels: lastScreenPixels, requestTotal: lastRequestTotal, appCommits: lastAppCommits, nodeCount: lastNodeCount }
|
|
1944
2002
|
if (snapshot.layoutDirty) dirtyPolls++
|
|
1945
2003
|
if (snapshot.animating || snapshot.shellAnimating) animatingPolls++
|
|
1946
2004
|
if (snapshot.webViewStarting) webViewStartingPolls++
|
|
@@ -1961,7 +2019,15 @@ async function waitForSootsimIdle({
|
|
|
1961
2019
|
// strictOk and adds shell motion plus the blocking-stats floor. a
|
|
1962
2020
|
// null count or commit reading means the runtime does not report
|
|
1963
2021
|
// it, which reads as stable the way a missing stats block does.
|
|
1964
|
-
|
|
2022
|
+
// native screen checks observe output, not animation ownership. after
|
|
2023
|
+
// its 3 s pixel phase, iOS accepts two equal native TreeNodes even
|
|
2024
|
+
// while paint-only playback continues. overlap hierarchy reads so
|
|
2025
|
+
// neither the gesture nor screenshot deadline grows.
|
|
2026
|
+
const maestroStill = snapshot.screenPixels !== null && !snapshot.workerBusy && !snapshot.webViewStarting && (
|
|
2027
|
+
!screenChanged || (clockNow() - start >= 3000 &&
|
|
2028
|
+
hierarchyUnchanged(snapshot.nativeHierarchy, lastNativeHierarchy))
|
|
2029
|
+
)
|
|
2030
|
+
const visuallyStill = maestro ? maestroStill :
|
|
1965
2031
|
strictOk &&
|
|
1966
2032
|
!snapshot.animating &&
|
|
1967
2033
|
!snapshot.layoutDirty &&
|
|
@@ -1989,7 +2055,7 @@ async function waitForSootsimIdle({
|
|
|
1989
2055
|
// grace (continuous background traffic must not block forever).
|
|
1990
2056
|
if (
|
|
1991
2057
|
stillProven() &&
|
|
1992
|
-
(motionOnly || networkQuiet || clockNow() - visuallyStillSince >= networkQuietGraceMs)
|
|
2058
|
+
(maestro || motionOnly || networkQuiet || clockNow() - visuallyStillSince >= networkQuietGraceMs)
|
|
1993
2059
|
) {
|
|
1994
2060
|
if (transitionWait) {
|
|
1995
2061
|
await transitionWait
|
|
@@ -2001,6 +2067,7 @@ async function waitForSootsimIdle({
|
|
|
2001
2067
|
stillPolls = []
|
|
2002
2068
|
visuallyStillSince = 0
|
|
2003
2069
|
}
|
|
2070
|
+
lastNativeHierarchy = snapshot.nativeHierarchy
|
|
2004
2071
|
lastLayout = snapshot.layout
|
|
2005
2072
|
lastScreenPixels = snapshot.screenPixels
|
|
2006
2073
|
lastRequestTotal = snapshot.requestTotal
|
|
@@ -2023,20 +2090,21 @@ async function waitForSootsimIdle({
|
|
|
2023
2090
|
}
|
|
2024
2091
|
const last = report.snapshot
|
|
2025
2092
|
const blockers = []
|
|
2026
|
-
if (strict && !last.renderStatsAvailable) blockers.push('render stats unavailable')
|
|
2027
|
-
if (last.animating) blockers.push('animations still running')
|
|
2028
|
-
if (last.shellAnimating) blockers.push('shell animations still running (' + last.shellBlockers + ')')
|
|
2029
|
-
if (last.layoutDirty) blockers.push('layout still dirty')
|
|
2030
|
-
if (last.appCommits !== null && report.appCommits !== null && last.appCommits !== report.appCommits) blockers.push('layout commits still landing')
|
|
2031
|
-
if (last.nodeCount !== null && report.nodeCount !== null && last.nodeCount !== report.nodeCount) blockers.push('node count still changing')
|
|
2032
|
-
if (!motionOnly && last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
2093
|
+
if (!maestro && strict && !last.renderStatsAvailable) blockers.push('render stats unavailable')
|
|
2094
|
+
if (!maestro && last.animating) blockers.push('animations still running')
|
|
2095
|
+
if (!maestro && last.shellAnimating) blockers.push('shell animations still running (' + last.shellBlockers + ')')
|
|
2096
|
+
if (!maestro && last.layoutDirty) blockers.push('layout still dirty')
|
|
2097
|
+
if (!maestro && last.appCommits !== null && report.appCommits !== null && last.appCommits !== report.appCommits) blockers.push('layout commits still landing')
|
|
2098
|
+
if (!maestro && last.nodeCount !== null && report.nodeCount !== null && last.nodeCount !== report.nodeCount) blockers.push('node count still changing')
|
|
2099
|
+
if (!maestro && !motionOnly && last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
2033
2100
|
if (last.workerBusy) blockers.push('a render worker too busy to report')
|
|
2034
2101
|
if (last.webViewStarting) blockers.push(last.webViewBlocker || 'webView still starting')
|
|
2035
|
-
if (last.layout !== report.layout) blockers.push('layout still changing')
|
|
2102
|
+
if (!maestro && last.layout !== report.layout) blockers.push('layout still changing')
|
|
2103
|
+
if (maestro && !hierarchyUnchanged(last.nativeHierarchy, report.nativeHierarchy)) blockers.push(last.nativeHierarchy === null ? 'native accessibility hierarchy unavailable' : 'native accessibility hierarchy still changing')
|
|
2036
2104
|
if (paintStill && !last.screenPixels) blockers.push('screen pixels unavailable')
|
|
2037
2105
|
else if (paintStill && !screenUnchanged(last.screenPixels, report.screenPixels)) blockers.push('screen pixels still changing')
|
|
2038
|
-
if (!motionOnly && last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
|
|
2039
|
-
else if (!motionOnly && last.requestTotal !== report.requestTotal) blockers.push('new requests issued')
|
|
2106
|
+
if (!maestro && !motionOnly && last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
|
|
2107
|
+
else if (!maestro && !motionOnly && last.requestTotal !== report.requestTotal) blockers.push('new requests issued')
|
|
2040
2108
|
if (polls < 2) blockers.push('sim too busy to poll twice')
|
|
2041
2109
|
// the last read is still: motion ended too near the deadline for the
|
|
2042
2110
|
// stillness window to hold before it.
|
|
@@ -2078,8 +2146,10 @@ async function waitForSootsimIdle({
|
|
|
2078
2146
|
async function waitReadyAndSettle(bridge, timeoutMs, options = {}) {
|
|
2079
2147
|
const start = Date.now();
|
|
2080
2148
|
const remaining = () => Math.max(0, start + timeoutMs - Date.now());
|
|
2149
|
+
let accepted = null;
|
|
2081
2150
|
const result = (status, idle2) => ({
|
|
2082
2151
|
status,
|
|
2152
|
+
accepted,
|
|
2083
2153
|
idle: idle2,
|
|
2084
2154
|
elapsedMs: Date.now() - start
|
|
2085
2155
|
});
|
|
@@ -2088,6 +2158,7 @@ async function waitReadyAndSettle(bridge, timeoutMs, options = {}) {
|
|
|
2088
2158
|
idle = null;
|
|
2089
2159
|
const ready = await inspectWaitReady(bridge, remaining(), options);
|
|
2090
2160
|
if (!ready.ready) return result(ready, idle);
|
|
2161
|
+
accepted = ready;
|
|
2091
2162
|
idle = await waitForSootsimIdle({
|
|
2092
2163
|
bridge,
|
|
2093
2164
|
simId: options.simId,
|
|
@@ -2511,6 +2582,20 @@ async function openAppUrl(bridge, target) {
|
|
|
2511
2582
|
return normalized;
|
|
2512
2583
|
}
|
|
2513
2584
|
|
|
2585
|
+
// src/launchMetadataContract.ts
|
|
2586
|
+
var LAUNCH_METADATA_QUERY_PARAM = "launchMetadata";
|
|
2587
|
+
var LAUNCH_METADATA_KEYS = [
|
|
2588
|
+
"appFonts",
|
|
2589
|
+
"appSplash",
|
|
2590
|
+
"appCatalog",
|
|
2591
|
+
"nativeAppIdentity",
|
|
2592
|
+
"nativeFirebase",
|
|
2593
|
+
"appManifest",
|
|
2594
|
+
"packageVersions",
|
|
2595
|
+
"dotEnv",
|
|
2596
|
+
"env"
|
|
2597
|
+
];
|
|
2598
|
+
|
|
2514
2599
|
// src/sleep.ts
|
|
2515
2600
|
function sleep(ms) {
|
|
2516
2601
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -2579,10 +2664,8 @@ var TARGET_SEARCH_PARAMS = [
|
|
|
2579
2664
|
"open",
|
|
2580
2665
|
"port",
|
|
2581
2666
|
"inspectOpen",
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
"appSplash",
|
|
2585
|
-
"appCatalog"
|
|
2667
|
+
...LAUNCH_METADATA_KEYS,
|
|
2668
|
+
LAUNCH_METADATA_QUERY_PARAM
|
|
2586
2669
|
];
|
|
2587
2670
|
function buildSimOpenUrl(currentUrl, target) {
|
|
2588
2671
|
const url = new URL(currentUrl);
|
|
@@ -3037,7 +3120,6 @@ export {
|
|
|
3037
3120
|
layoutGetNativeEval,
|
|
3038
3121
|
rankInteractive,
|
|
3039
3122
|
readyProbeHasContent,
|
|
3040
|
-
readyProbeHasTargetContent,
|
|
3041
3123
|
readyProbeIsReady,
|
|
3042
3124
|
resolveFindMode,
|
|
3043
3125
|
resolveMaxMsFlag,
|