peachsim 0.1.1406 → 0.1.1463
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 +8 -4
- package/README.md +22 -2
- package/cli/app-fonts.ts +50 -44
- package/cli/bin.ts +5 -4
- package/cli/bridge-diagnostics.ts +5 -0
- package/cli/bridge-flow-runner.ts +21 -13
- package/cli/cloud-client.ts +4 -3
- package/cli/commands/control.ts +155 -123
- package/cli/commands/daemon-mac-app.ts +3 -3
- package/cli/commands/daemon.ts +2 -2
- package/cli/commands/do-chain.ts +9 -2
- package/cli/commands/electron.ts +4 -1
- package/cli/commands/inspect/core.ts +1 -1
- package/cli/commands/inspect/settle.ts +19 -7
- package/cli/commands/inspect/settling.ts +92 -56
- package/cli/commands/inspect/wait-idle.ts +21 -9
- package/cli/commands/inspect/wait-ready.ts +22 -8
- package/cli/commands/inspect.ts +101 -134
- package/cli/commands/setup.ts +26 -16
- package/cli/commands/upgrade.ts +53 -9
- package/cli/desktop-companion.ts +1 -1
- package/cli/drivers/playwright-sim-host.ts +22 -13
- package/cli/drivers/playwright.ts +3 -3
- package/cli/main.ts +14 -5
- package/cli/outbound-endpoints.ts +1 -9
- package/detox/index.ts +6 -1
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- 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 +3 -3
- package/dist-lib/bridge-contract.mjs +3 -3
- package/dist-lib/bundle-channel.cjs +322 -274
- 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 +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +322 -45
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +69 -33
- package/dist-lib/expo-swift-metadata.cjs +1 -1
- package/dist-lib/expo-swift-metadata.mjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +3650 -3528
- 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 +327 -123
- 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 +10 -5
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- 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 +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +49 -47
- package/dist-lib/native-app-identity-project.cjs +1 -1
- package/dist-lib/native-app-identity-project.mjs +1 -1
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- 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 +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +23 -17
- package/dist-lib/sdk.cjs +99 -61
- package/dist-lib/sdk.mjs +97 -61
- package/dist-lib/skills.cjs +2959 -2780
- package/dist-lib/swift-compile.cjs +26 -12
- package/dist-lib/swift-compile.mjs +26 -12
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +2 -2
- package/dist-lib/swift-submit.mjs +2 -2
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +66 -31
- package/dist-lib/vite.cjs +1 -1
- package/dist-lib/worklet-executable.cjs +1 -1
- package/dist-lib/worklet-executable.mjs +1 -1
- package/kotlin/AppSources/android/view/Window.kt +2 -0
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +1 -1
- package/kotlin/ComposeSources/PeachComposeHost.kt +35 -9
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +2 -2
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +9 -6
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +4 -4
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +2 -2
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +22 -8
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +0 -3
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +10 -9
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +6 -5
- package/kotlin/fixtures/import-drawing/Drawing.d.kt.ts +7 -0
- package/kotlin/fixtures/import-drawing/Drawing.kt +101 -0
- package/kotlin/fixtures/import-drawing/ImportDrawing.native.tsx +18 -0
- package/kotlin/fixtures/import-drawing/README.md +34 -0
- package/kotlin/fixtures/import-drawing/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-drawing/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-drawing/package.json +23 -0
- package/kotlin/fixtures/import-drawing/tsconfig.json +20 -0
- package/kotlin/fixtures/import-drawing/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportNested.native.tsx +10 -0
- package/kotlin/fixtures/import-scroll/Nested.d.kt.ts +4 -0
- package/kotlin/fixtures/import-scroll/README.md +15 -0
- package/kotlin/fixtures/import-scroll/app/nested+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +26 -0
- package/kotlin/fixtures/import-values/README.md +6 -1
- package/kotlin/fixtures/import-values/Values.d.kt.ts +4 -0
- package/kotlin/fixtures/import-values/Values.kt +18 -0
- package/kotlin/tools/expo-types.main.kts +17 -5
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +33 -23
- package/src/assetCatalogContract.ts +7 -0
- package/src/bridge-contract.ts +21 -3
- package/src/connect.ts +18 -5
- package/src/desktop-host-delivery.ts +33 -3
- package/src/expo-swift-host.ts +6 -3
- package/src/host/bridge-host.ts +2 -0
- package/src/host/fetch-proxy-transport.ts +8 -0
- package/src/kotlin-host.ts +11 -5
- package/src/native-firebase-config.ts +95 -54
- package/src/process-output.ts +16 -0
- package/src/sdk.ts +6 -1
- package/src/sim-client.ts +6 -1
- package/src/swift-compile.ts +36 -15
- package/src/swift-distribution.lock.json +8 -8
- package/src/swift-standin-emit.ts +10 -1
- package/src/swift-standins.ts +21 -7
- package/src/swift-submit.ts +6 -1
- /package/kotlin/fixtures/{kotlin-app-variants → import-scroll}/Nested.kt +0 -0
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.1463 | (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);
|
|
@@ -7,10 +7,10 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
7
7
|
var SEMANTIC_READY_CONTENT_NODE_FLOOR = 100;
|
|
8
8
|
var HEADLESS_TENANT_FETCH_HUNG_MARKER = "headless tenant fetch hung";
|
|
9
9
|
function readyProbeHasContent(probe) {
|
|
10
|
-
return (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0 || probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
|
|
10
|
+
return probe.paintedAppContent === true || (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0 || probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
|
|
11
11
|
}
|
|
12
12
|
function readyProbeHasTargetContent(probe) {
|
|
13
|
-
return (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0;
|
|
13
|
+
return probe.paintedAppContent === true || (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0;
|
|
14
14
|
}
|
|
15
15
|
function readyProbeIsReady(probe) {
|
|
16
16
|
return (probe.flag === true ? readyProbeHasContent(probe) : readyProbeHasTargetContent(probe)) && probe.externalReady !== false && !probe.externalError && !probe.loadingText;
|
|
@@ -1336,7 +1336,7 @@ function formatTimelinePayload(kind, d) {
|
|
|
1336
1336
|
case "notification":
|
|
1337
1337
|
return `${d.title ?? ""}${d.body ? ` \u2014 ${d.body}` : ""}`;
|
|
1338
1338
|
case "fetch":
|
|
1339
|
-
return `${d.method ?? "GET"} ${d.url ?? ""}${d.status ? ` -> ${d.status}` : ""}`;
|
|
1339
|
+
return `${d.method ?? "GET"} ${d.url ?? ""}${d.status ? ` -> ${d.status}` : ""}${d.error ? ` -> ${d.error}` : ""}`;
|
|
1340
1340
|
case "console":
|
|
1341
1341
|
case "console-log":
|
|
1342
1342
|
return `${d.level ?? "log"}: ${(d.message ?? "").toString().slice(0, 120)}`;
|
|
@@ -1431,6 +1431,18 @@ var RuntimeReadinessUnsupportedError = class extends Error {
|
|
|
1431
1431
|
this.name = "RuntimeReadinessUnsupportedError";
|
|
1432
1432
|
}
|
|
1433
1433
|
};
|
|
1434
|
+
var IdleObservationError = class extends Error {
|
|
1435
|
+
constructor(elapsedMs, failure) {
|
|
1436
|
+
const detail = failure instanceof Error ? failure.message : String(failure);
|
|
1437
|
+
super(`idle observation failed after ${elapsedMs}ms: ${detail}`, {
|
|
1438
|
+
cause: failure
|
|
1439
|
+
});
|
|
1440
|
+
this.elapsedMs = elapsedMs;
|
|
1441
|
+
this.failure = failure;
|
|
1442
|
+
__publicField(this, "code", "idle_observation_failed");
|
|
1443
|
+
this.name = "IdleObservationError";
|
|
1444
|
+
}
|
|
1445
|
+
};
|
|
1434
1446
|
async function waitForSootsimIdle({
|
|
1435
1447
|
bridge,
|
|
1436
1448
|
simId,
|
|
@@ -1441,6 +1453,7 @@ async function waitForSootsimIdle({
|
|
|
1441
1453
|
paintStill = false
|
|
1442
1454
|
}) {
|
|
1443
1455
|
let result;
|
|
1456
|
+
const observationStartedAt = Date.now();
|
|
1444
1457
|
try {
|
|
1445
1458
|
result = await bridge.send(
|
|
1446
1459
|
{
|
|
@@ -1471,27 +1484,23 @@ async function waitForSootsimIdle({
|
|
|
1471
1484
|
let screenPixels = null
|
|
1472
1485
|
try {
|
|
1473
1486
|
|
|
1474
|
-
//
|
|
1475
|
-
//
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
// transition FIRST, bounded by the overall budget. when no
|
|
1480
|
-
// transition is happening this returns in ~80ms (startWindowMs), so
|
|
1481
|
-
// a plain button tap barely pays for it.
|
|
1482
|
-
try {
|
|
1483
|
-
const wfst = window.__sootsimTest?.waitForScreenTransitions
|
|
1484
|
-
if (typeof wfst === 'function') {
|
|
1487
|
+
// discover transitions while observing layout. when motion starts,
|
|
1488
|
+
// observations from before its completion cannot prove the new screen.
|
|
1489
|
+
let transitionWait = (async () => {
|
|
1490
|
+
try {
|
|
1491
|
+
const wfst = window.__sootsimTest?.waitForScreenTransitions
|
|
1485
1492
|
const remaining = deadline - Date.now()
|
|
1486
|
-
if (remaining > 120) {
|
|
1487
|
-
await wfst({
|
|
1493
|
+
if (typeof wfst === 'function' && remaining > 120) {
|
|
1494
|
+
const transition = await wfst({
|
|
1488
1495
|
timeoutMs: Math.min(remaining - 80, 4000),
|
|
1489
1496
|
settleMs: 64,
|
|
1490
1497
|
startWindowMs: 80,
|
|
1491
1498
|
})
|
|
1499
|
+
return transition?.started === true
|
|
1492
1500
|
}
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1501
|
+
} catch {}
|
|
1502
|
+
return false
|
|
1503
|
+
})()
|
|
1495
1504
|
|
|
1496
1505
|
// a worker that cannot answer within the remaining budget is busy, not
|
|
1497
1506
|
// idle: its poll reads as unsettled. bounding each read by the budget
|
|
@@ -1516,17 +1525,51 @@ async function waitForSootsimIdle({
|
|
|
1516
1525
|
let nodeCount = null
|
|
1517
1526
|
let renderStatsAvailable = false
|
|
1518
1527
|
let shellAnimating = false
|
|
1528
|
+
let shellBlockers = ''
|
|
1519
1529
|
let webViewStarting = false
|
|
1520
1530
|
let webViewBlocker = ''
|
|
1531
|
+
// the reads are independent, so they run concurrently: a loaded sim
|
|
1532
|
+
// answers each one late, and a poll that waits for them in turn
|
|
1533
|
+
// costs their sum, which fits too few polls in the budget to settle.
|
|
1521
1534
|
// strict also waits out shell motion: a system alert, sheet or menu
|
|
1522
1535
|
// animates in the shell worker while the app's own stats read still,
|
|
1523
1536
|
// so its presentation is complete only once the shell's list empties.
|
|
1524
|
-
|
|
1525
|
-
|
|
1537
|
+
const motionRead = strict
|
|
1538
|
+
? answer(() => window.__sootsimTest?.listAnimations?.()).catch(() => null)
|
|
1539
|
+
: null
|
|
1540
|
+
const statsRead = answer(() => window.__sootsimRenderHost?.queryStats?.()).catch(() => null)
|
|
1541
|
+
// image preparation ends in the tenant before the compositor decodes
|
|
1542
|
+
// and realizes its pixels. both owners must finish before settling.
|
|
1543
|
+
// the compositor rejects a stats request it is too busy to answer.
|
|
1544
|
+
const compositorRead = answer(() => window.__sootsimCompositor.getStats()).catch(() => BUSY)
|
|
1545
|
+
const countsRead = Promise.resolve().then(() => window.__sootsimTest?.getRequestCounts?.()).catch(() => null)
|
|
1546
|
+
// mounted-root membership: the live node count moves while the tree
|
|
1547
|
+
// mounts, unmounts or recycles, in either render mode.
|
|
1548
|
+
const nodeCountRead = Promise.resolve().then(() => window.__sootsimTest?.getNodeCount?.()).catch(() => null)
|
|
1549
|
+
// the mounted hierarchy in render-worker mode comes from the test
|
|
1550
|
+
// bridge: window.__sootsimRoot is an empty placeholder there, so a
|
|
1551
|
+
// walk over it hashes every screen to the same empty string while
|
|
1552
|
+
// it moves. listInspectable is the worker-backed read describe
|
|
1553
|
+
// uses; a worker too busy to answer it reads as unsettled. tight
|
|
1554
|
+
// budgets skip this read and settle on the cheaper signals above.
|
|
1555
|
+
const hierarchyRead =
|
|
1556
|
+
fullGeometry && typeof window.__sootsimTest?.listInspectable === 'function'
|
|
1557
|
+
? answer(() => window.__sootsimTest.listInspectable({})).catch(() => null)
|
|
1558
|
+
: null
|
|
1559
|
+
if (motionRead) {
|
|
1560
|
+
const motion = await motionRead
|
|
1526
1561
|
if (motion === BUSY) workerBusy = true
|
|
1527
|
-
else
|
|
1562
|
+
else if (Array.isArray(motion)) {
|
|
1563
|
+
const blocking = motion.filter((anim) => anim.realm === 'shell' && anim.priority !== 'low')
|
|
1564
|
+
shellAnimating = blocking.length > 0
|
|
1565
|
+
// name what holds the settle so a timeout points at its owner.
|
|
1566
|
+
shellBlockers = blocking
|
|
1567
|
+
.slice(0, 4)
|
|
1568
|
+
.map((anim) => anim.source + '/' + anim.kind + '#' + anim.id + ' at ' + anim.current + (anim.loop ? ' loop' : ''))
|
|
1569
|
+
.join(', ')
|
|
1570
|
+
}
|
|
1528
1571
|
}
|
|
1529
|
-
const stats = await
|
|
1572
|
+
const stats = await statsRead
|
|
1530
1573
|
if (stats === BUSY) {
|
|
1531
1574
|
workerBusy = true
|
|
1532
1575
|
} else if (stats) {
|
|
@@ -1563,10 +1606,7 @@ async function waitForSootsimIdle({
|
|
|
1563
1606
|
// mounting or remounting, even with no animation flag raised.
|
|
1564
1607
|
appCommits = typeof stats.appCommitCount === 'number' ? stats.appCommitCount : null
|
|
1565
1608
|
}
|
|
1566
|
-
|
|
1567
|
-
// and realizes its pixels. both owners must finish before settling.
|
|
1568
|
-
// the compositor rejects a stats request it is too busy to answer.
|
|
1569
|
-
const compositor = await answer(() => window.__sootsimCompositor.getStats()).catch(() => BUSY)
|
|
1609
|
+
const compositor = await compositorRead
|
|
1570
1610
|
if (compositor === BUSY) {
|
|
1571
1611
|
workerBusy = true
|
|
1572
1612
|
} else {
|
|
@@ -1577,31 +1617,12 @@ async function waitForSootsimIdle({
|
|
|
1577
1617
|
webViewBlocker = 'compositor webView capture not settled'
|
|
1578
1618
|
}
|
|
1579
1619
|
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
// mounts, unmounts or recycles, in either render mode.
|
|
1587
|
-
try {
|
|
1588
|
-
const total = await window.__sootsimTest?.getNodeCount?.()
|
|
1589
|
-
nodeCount = typeof total === 'number' ? total : null
|
|
1590
|
-
} catch {}
|
|
1591
|
-
// the mounted hierarchy in render-worker mode comes from the test
|
|
1592
|
-
// bridge: window.__sootsimRoot is an empty placeholder there, so a
|
|
1593
|
-
// walk over it hashes every screen to the same empty string while
|
|
1594
|
-
// it moves. listInspectable is the worker-backed read describe
|
|
1595
|
-
// uses; a worker too busy to answer it reads as unsettled. tight
|
|
1596
|
-
// budgets skip this read and settle on the cheaper signals above.
|
|
1597
|
-
let hierarchy = null
|
|
1598
|
-
if (fullGeometry && typeof window.__sootsimTest?.listInspectable === 'function') {
|
|
1599
|
-
try {
|
|
1600
|
-
hierarchy = await answer(() => window.__sootsimTest.listInspectable({}))
|
|
1601
|
-
} catch {
|
|
1602
|
-
hierarchy = null
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1620
|
+
const counts = await countsRead
|
|
1621
|
+
requestTotal = typeof counts?.total === 'number' ? counts.total : 0
|
|
1622
|
+
requestInFlight = typeof counts?.inFlight === 'number' ? counts.inFlight : 0
|
|
1623
|
+
const total = await nodeCountRead
|
|
1624
|
+
nodeCount = typeof total === 'number' ? total : null
|
|
1625
|
+
let hierarchy = hierarchyRead ? await hierarchyRead : null
|
|
1605
1626
|
if (hierarchy === BUSY) {
|
|
1606
1627
|
workerBusy = true
|
|
1607
1628
|
hierarchy = null
|
|
@@ -1677,7 +1698,7 @@ async function waitForSootsimIdle({
|
|
|
1677
1698
|
pixelFrameToken = token
|
|
1678
1699
|
}
|
|
1679
1700
|
}
|
|
1680
|
-
return { layout: nodes.join(';'), screenPixels, animating, shellAnimating, layoutDirty, pendingFetches, workerBusy, webViewStarting, webViewBlocker, renderStatsAvailable, requestTotal, requestInFlight, appCommits, nodeCount }
|
|
1701
|
+
return { layout: nodes.join(';'), screenPixels, animating, shellAnimating, shellBlockers, layoutDirty, pendingFetches, workerBusy, webViewStarting, webViewBlocker, renderStatsAvailable, requestTotal, requestInFlight, appCommits, nodeCount }
|
|
1681
1702
|
}
|
|
1682
1703
|
|
|
1683
1704
|
// how long generic background network is allowed to keep us waiting AFTER
|
|
@@ -1764,6 +1785,19 @@ async function waitForSootsimIdle({
|
|
|
1764
1785
|
Date.now() - visuallyStillSince >= requiredStillMs &&
|
|
1765
1786
|
(networkQuiet || Date.now() - visuallyStillSince >= networkQuietGraceMs)
|
|
1766
1787
|
) {
|
|
1788
|
+
if (transitionWait) {
|
|
1789
|
+
const started = await transitionWait
|
|
1790
|
+
transitionWait = null
|
|
1791
|
+
if (started) {
|
|
1792
|
+
lastLayout = ''
|
|
1793
|
+
lastRequestTotal = -1
|
|
1794
|
+
lastAppCommits = null
|
|
1795
|
+
lastNodeCount = null
|
|
1796
|
+
stable = 0
|
|
1797
|
+
visuallyStillSince = 0
|
|
1798
|
+
continue
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1767
1801
|
return { settled: true, elapsed: Date.now() - start, blockedBy: '' }
|
|
1768
1802
|
}
|
|
1769
1803
|
} else {
|
|
@@ -1782,7 +1816,7 @@ async function waitForSootsimIdle({
|
|
|
1782
1816
|
const blockers = []
|
|
1783
1817
|
if (strict && !last.renderStatsAvailable) blockers.push('render stats unavailable')
|
|
1784
1818
|
if (last.animating) blockers.push('animations still running')
|
|
1785
|
-
if (last.shellAnimating) blockers.push('shell animations still running')
|
|
1819
|
+
if (last.shellAnimating) blockers.push('shell animations still running (' + last.shellBlockers + ')')
|
|
1786
1820
|
if (last.layoutDirty) blockers.push('layout still dirty')
|
|
1787
1821
|
if (last.appCommits !== null && lastAppCommits !== null && last.appCommits !== lastAppCommits) blockers.push('layout commits still landing')
|
|
1788
1822
|
if (last.nodeCount !== null && lastNodeCount !== null && last.nodeCount !== lastNodeCount) blockers.push('node count still changing')
|
|
@@ -1813,12 +1847,7 @@ async function waitForSootsimIdle({
|
|
|
1813
1847
|
}
|
|
1814
1848
|
);
|
|
1815
1849
|
} catch (error) {
|
|
1816
|
-
|
|
1817
|
-
return {
|
|
1818
|
-
settled: false,
|
|
1819
|
-
elapsed: maxMs,
|
|
1820
|
-
blockedBy: message
|
|
1821
|
-
};
|
|
1850
|
+
throw new IdleObservationError(Math.max(0, Date.now() - observationStartedAt), error);
|
|
1822
1851
|
}
|
|
1823
1852
|
if (result?.error === "runtime_readiness_unsupported" && typeof result.runtimeVersion === "string" && Array.isArray(result.missingFields) && result.missingFields.every((field) => typeof field === "string")) {
|
|
1824
1853
|
throw new RuntimeReadinessUnsupportedError(
|
|
@@ -2453,7 +2482,12 @@ var SimClient = class {
|
|
|
2453
2482
|
if (!status.ready) throw new SimReadyTimeoutError(status);
|
|
2454
2483
|
return status;
|
|
2455
2484
|
}
|
|
2456
|
-
/**
|
|
2485
|
+
/**
|
|
2486
|
+
* wait for layout/animation/transition settle after an interaction.
|
|
2487
|
+
* a still-busy guest returns settled false with its own elapsed time.
|
|
2488
|
+
* a failed idle read throws IdleObservationError with the host elapsed
|
|
2489
|
+
* time and the original failure.
|
|
2490
|
+
*/
|
|
2457
2491
|
settle(opts = {}) {
|
|
2458
2492
|
return waitForSootsimIdle({
|
|
2459
2493
|
bridge: this,
|
|
@@ -2724,9 +2758,11 @@ var SimClient = class {
|
|
|
2724
2758
|
};
|
|
2725
2759
|
export {
|
|
2726
2760
|
DEBUG_CHANNELS,
|
|
2761
|
+
IdleObservationError,
|
|
2727
2762
|
LAYOUT_GET_NATIVE_EVAL,
|
|
2728
2763
|
MERGED_CONSOLE_COUNT_EVAL,
|
|
2729
2764
|
NOISY_TIMELINE_KINDS,
|
|
2765
|
+
RuntimeReadinessUnsupportedError,
|
|
2730
2766
|
SimClient,
|
|
2731
2767
|
SimClientError,
|
|
2732
2768
|
SimConnectError,
|