peachsim 0.1.939 → 0.1.1399
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 +28 -22
- package/cli/app-catalog.ts +29 -14
- package/cli/app-fonts.ts +5 -3
- package/cli/bridge-flow-runner.ts +40 -29
- package/cli/cloud-client.ts +57 -21
- package/cli/cloud-test-tunnel.ts +12 -18
- package/cli/commands/agent.ts +1 -1
- package/cli/commands/app-fonts.ts +3 -3
- package/cli/commands/assert.ts +8 -8
- package/cli/commands/auth.ts +8 -3
- package/cli/commands/box/bundle-plane.ts +13 -1
- package/cli/commands/box.ts +16 -5
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +125 -71
- package/cli/commands/cpu-profile.ts +45 -1
- package/cli/commands/daemon.ts +131 -33
- package/cli/commands/debug.ts +24 -17
- package/cli/commands/desktop.ts +7 -1
- package/cli/commands/detect.ts +101 -0
- package/cli/commands/detox.ts +6 -6
- package/cli/commands/device.ts +12 -12
- package/cli/commands/electron.ts +32 -14
- package/cli/commands/flow.ts +49 -41
- package/cli/commands/guest-host.ts +39 -1
- package/cli/commands/inspect/core.ts +14 -8
- package/cli/commands/inspect/list.ts +1 -1
- package/cli/commands/inspect/settle.ts +5 -3
- package/cli/commands/inspect/settling.ts +229 -44
- package/cli/commands/inspect/wait-idle.ts +3 -2
- package/cli/commands/inspect.ts +105 -93
- package/cli/commands/install-cli.ts +36 -15
- package/cli/commands/install-desktop.ts +68 -195
- package/cli/commands/kotlin.ts +6 -5
- package/cli/commands/login.ts +5 -5
- package/cli/commands/maestro-compare.ts +554 -0
- package/cli/commands/maestro-generate.ts +6 -3
- package/cli/commands/maestro.ts +22 -0
- package/cli/commands/mode.ts +2 -2
- package/cli/commands/no-bridge-hint.ts +6 -2
- package/cli/commands/platform.ts +35 -6
- package/cli/commands/preview.ts +6 -0
- package/cli/commands/project-report.ts +10 -12
- package/cli/commands/record.ts +37 -37
- package/cli/commands/runtime.ts +9 -9
- package/cli/commands/screenshot-layers.ts +4 -4
- package/cli/commands/screenshot-mode.ts +2 -2
- package/cli/commands/screenshot.ts +8 -8
- package/cli/commands/screenshots-capture.ts +2 -2
- package/cli/commands/serve.ts +9 -12
- package/cli/commands/setup.ts +29 -14
- package/cli/commands/shell-boolean-mode.ts +2 -2
- package/cli/commands/show-touches-mode.ts +2 -2
- package/cli/commands/skills.ts +11 -11
- package/cli/commands/swift.ts +29 -11
- package/cli/commands/telemetry.ts +2 -2
- package/cli/commands/test.ts +5 -0
- package/cli/commands/three-mode.ts +3 -3
- package/cli/commands/timeline.ts +4 -4
- package/cli/commands/upgrade.ts +2 -2
- package/cli/commands/upload.ts +15 -15
- package/cli/commands/what-happened.ts +2 -2
- package/cli/current-sim.ts +6 -3
- package/cli/desktop-companion.ts +55 -149
- package/cli/dev-build-freshness.ts +2 -2
- package/cli/drivers/desktop.ts +17 -9
- package/cli/drivers/electron.ts +1 -2
- package/cli/drivers/playwright-sim-host.ts +11 -2
- package/cli/drivers/playwright.ts +35 -2
- package/cli/drivers/types.ts +8 -0
- package/cli/maestro-compare.ts +670 -0
- package/cli/outbound-endpoints.ts +46 -8
- package/cli/recording-access.ts +6 -6
- package/cli/run-registry.ts +1 -1
- package/cli/runtime-compat.ts +5 -1
- package/cli/send-to-box.ts +3 -3
- package/cli/shell-init.ts +2 -1
- package/cli/ws-bridge.ts +9 -5
- package/detox/element-types.ts +1 -0
- package/detox/gestures.ts +3 -3
- package/detox/index.ts +67 -38
- package/detox/navigation-lifecycle.ts +9 -6
- package/detox/proof-frame.cjs +6 -4
- 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 +42 -17
- package/dist-lib/bridge-contract-input.mjs +41 -16
- package/dist-lib/bridge-contract.cjs +1 -4
- package/dist-lib/bridge-contract.mjs +1 -3
- package/dist-lib/bundle-channel.cjs +2918 -550
- package/dist-lib/capture-contract.cjs +65 -24
- package/dist-lib/capture-contract.mjs +63 -24
- package/dist-lib/cloud-contract.cjs +2 -2
- package/dist-lib/cloud-contract.mjs +2 -2
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +3 -3
- package/dist-lib/cloud.mjs +3 -3
- package/dist-lib/config.cjs +15 -5
- package/dist-lib/config.mjs +154 -0
- package/dist-lib/detox/index.cjs +495 -139
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +1168 -238
- package/dist-lib/expo-swift-metadata.cjs +34 -23
- package/dist-lib/expo-swift-metadata.mjs +32 -23
- package/dist-lib/home-paths.cjs +2 -2
- package/dist-lib/host/bridge-host.cjs +2938 -654
- package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
- package/dist-lib/host/replacement-module-handler.cjs +2 -2
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +999 -353
- 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 +332 -19
- 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 +7 -7
- package/dist-lib/metro-production-bundle.mjs +5 -5
- package/dist-lib/metro.cjs +688 -250
- package/dist-lib/native-app-identity-project.cjs +2647 -0
- package/dist-lib/native-app-identity-project.mjs +1257 -0
- package/dist-lib/native-app-identity.cjs +325 -25
- package/dist-lib/native-app-identity.mjs +323 -25
- 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 +5 -1
- package/dist-lib/react-native-host-modules.mjs +5 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
- package/dist-lib/sdk.cjs +231 -51
- package/dist-lib/sdk.mjs +231 -51
- package/dist-lib/skills.cjs +4107 -1374
- package/dist-lib/swift-compile.cjs +290 -30
- package/dist-lib/swift-compile.mjs +290 -30
- package/dist-lib/swift-package.cjs +143 -12
- package/dist-lib/swift-package.mjs +137 -11
- package/dist-lib/swift-submit.cjs +47 -5
- package/dist-lib/swift-submit.mjs +42 -5
- package/dist-lib/swift-toolchain.cjs +7 -2
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1392 -458
- package/dist-lib/vite.cjs +13 -17
- package/dist-lib/worklet-executable.cjs +248 -33
- package/dist-lib/worklet-executable.mjs +248 -33
- package/install.sh +10 -1
- package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
- package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
- package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
- package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
- package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
- package/kotlin/AppSources/android/view/Window.kt +36 -0
- package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
- package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
- package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
- package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
- package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
- package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
- package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
- package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
- package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
- package/kotlin/README.md +13 -3
- package/kotlin/Sources/android/os/Build.kt +17 -0
- package/kotlin/Sources/android/os/Handler.kt +35 -0
- package/kotlin/Sources/android/os/Looper.kt +17 -0
- package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
- package/kotlin/Sources/android/os/SystemClock.kt +14 -0
- package/kotlin/Sources/android/util/Log.kt +64 -0
- package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
- package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
- package/kotlin/Sources/org/json/JSON.kt +44 -0
- package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
- package/kotlin/fixtures/counter/Counter.kt +10 -3
- package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
- package/kotlin/fixtures/counter/vite.config.ts +2 -2
- package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
- package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-animation/Animation.kt +80 -0
- package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
- package/kotlin/fixtures/import-animation/README.md +24 -0
- package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
- package/kotlin/fixtures/import-animation/package.json +23 -0
- package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
- package/kotlin/fixtures/import-editor/Editor.kt +59 -0
- package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
- package/kotlin/fixtures/import-editor/README.md +27 -0
- package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-editor/package.json +23 -0
- package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
- package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
- package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
- package/kotlin/fixtures/import-effects/Effects.kt +87 -0
- package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
- package/kotlin/fixtures/import-effects/README.md +19 -0
- package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-effects/package.json +23 -0
- package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
- package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
- package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
- package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
- package/kotlin/fixtures/import-layout/Layout.kt +72 -0
- package/kotlin/fixtures/import-layout/README.md +24 -0
- package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-layout/package.json +23 -0
- package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
- package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
- package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
- package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
- package/kotlin/fixtures/import-navigation/README.md +31 -0
- package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-navigation/package.json +23 -0
- package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
- package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
- package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
- package/kotlin/fixtures/import-overlays/README.md +34 -0
- package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-overlays/package.json +23 -0
- package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
- package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
- package/kotlin/fixtures/import-scroll/README.md +23 -0
- package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
- package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
- package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-scroll/package.json +23 -0
- package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
- package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
- package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
- package/kotlin/fixtures/import-selection/README.md +32 -0
- package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
- package/kotlin/fixtures/import-selection/Selection.kt +78 -0
- package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-selection/package.json +23 -0
- package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
- package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
- package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
- package/kotlin/fixtures/import-surfaces/README.md +22 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
- package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-surfaces/package.json +23 -0
- package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
- package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
- package/kotlin/fixtures/import-values/README.md +23 -0
- package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
- package/kotlin/fixtures/import-values/Values.kt +66 -0
- package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/package.json +23 -0
- package/kotlin/fixtures/import-values/tsconfig.json +20 -0
- package/kotlin/fixtures/import-values/vite.config.ts +20 -0
- package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
- package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
- package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
- package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
- package/kotlin/fork/NOTICE +6 -1
- package/kotlin/fork/README.md +15 -7
- package/kotlin/fork/build.sh +2 -0
- package/kotlin/fork/compose-worker-globals.patch +186 -4
- package/kotlin/fork/fork.json +2 -2
- package/kotlin/fork/skiko-worker-clock.patch +12 -0
- package/kotlin/toolchain.json +12 -12
- package/kotlin/tools/expo-types.main.kts +115 -0
- package/package.json +17 -23
- package/scripts/dev-server-scanner.ts +92 -66
- package/skills/contrast/SKILL.md +2 -2
- package/skills/peach-debug/SKILL.md +1 -1
- package/skills/peach-perf/SKILL.md +1 -1
- package/skills/peach-setup/SKILL.md +2 -1
- package/skills/peach-test/SKILL.md +8 -0
- package/src/assetCatalogContract.ts +43 -1
- package/src/bridge-contract-input.ts +46 -19
- package/src/bridge-contract.ts +0 -1
- package/src/bundle-channel.mjs +197 -84
- package/src/bundleGlobalFooter.ts +38 -0
- package/src/capture-contract.ts +107 -33
- package/src/cloud-contract.ts +5 -1
- package/src/cloud.ts +5 -2
- package/src/config.ts +22 -3
- package/src/configured-bundle-producer.ts +1 -1
- package/src/desktop-host-delivery.ts +95 -1
- package/src/expo-kotlin-bundle.ts +29 -0
- package/src/expo-kotlin-host.ts +201 -0
- package/src/expo-swift-host.ts +96 -76
- package/src/expoKotlinContract.ts +70 -0
- package/src/expoSwiftContract.ts +4 -25
- package/src/home-paths.ts +7 -4
- package/src/host/bridge-host.ts +23 -3
- package/src/host/fetch-proxy-handler.ts +13 -0
- package/src/host/fetch-proxy-overrides.ts +11 -0
- package/src/host/replacement-module-handler.ts +5 -2
- package/src/index.ts +3 -1
- package/src/kotlin-host.ts +463 -19
- package/src/metro-plugin.ts +56 -28
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-app-identity-project.ts +190 -0
- package/src/native-app-identity.ts +398 -34
- package/src/native-firebase-config.ts +69 -15
- package/src/native-seam-manifest.ts +6 -0
- package/src/one-widget-discovery.ts +2 -1
- package/src/openstep-plist.ts +107 -0
- package/src/react-native-host-modules.ts +4 -0
- package/src/runtime-assets.ts +2 -2
- package/src/sim-client.ts +2 -2
- package/src/swift-binary-modules.ts +3 -1
- package/src/swift-compile.ts +286 -38
- package/src/swift-distribution-contract.ts +4 -0
- package/src/swift-distribution.lock.json +123 -12
- package/src/swift-distribution.ts +7 -3
- package/src/swift-host.ts +298 -83
- package/src/swift-package-manifest.ts +29 -2
- package/src/swift-package.ts +180 -10
- package/src/swift-packages.ts +4 -0
- package/src/swift-standin-emit.ts +4 -1
- package/src/swift-standins.ts +274 -15
- package/src/swift-submit.ts +62 -7
- package/src/swift-toolchain.ts +6 -1
- package/src/swiftContract.ts +126 -3
- package/src/vite-plugin-one.ts +13 -16
- package/src/vite-plugin-swift.ts +4 -5
- package/src/vite-plugin.ts +360 -144
- package/src/vite.d.ts +1 -1
- package/src/worker-system-chunks.ts +221 -0
- package/src/worklet-executable.ts +348 -38
- package/src/worklets-babel.ts +1 -1
- package/src/xcode-project.ts +243 -127
- package/dist-lib/agent-identity.cjs +0 -39
- package/dist-lib/agent-sessions.cjs +0 -760
- package/dist-lib/cli-constants.cjs +0 -32
- package/dist-lib/render-mode.cjs +0 -44
- package/kotlin/AppSources/android/view/View.kt +0 -74
- package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
- package/src/render-mode.ts +0 -15
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
- /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/*!
|
|
1
|
+
/*! peach v0.1.1399 | (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);
|
|
5
5
|
|
|
6
6
|
// src/bridge-contract.ts
|
|
7
7
|
var SEMANTIC_READY_CONTENT_NODE_FLOOR = 100;
|
|
8
|
-
var PUBLIC_NO_NETWORK_MARKER = "public Peach Cloud simulators have no network";
|
|
9
8
|
var HEADLESS_TENANT_FETCH_HUNG_MARKER = "headless tenant fetch hung";
|
|
10
9
|
function readyProbeHasContent(probe) {
|
|
11
10
|
return (probe.browserSurfaceCount ?? 0) > 0 || probe.liveFrameActive || probe.targets > 0 || probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
|
|
@@ -746,7 +745,7 @@ function shellEscape(value) {
|
|
|
746
745
|
}
|
|
747
746
|
function waitReadyReason(status) {
|
|
748
747
|
if (status.bridgeError) {
|
|
749
|
-
if (status.bridgeError.includes(HEADLESS_TENANT_FETCH_HUNG_MARKER)
|
|
748
|
+
if (status.bridgeError.includes(HEADLESS_TENANT_FETCH_HUNG_MARKER)) {
|
|
750
749
|
return status.bridgeError;
|
|
751
750
|
}
|
|
752
751
|
return `sim unreachable: ${status.bridgeError} \u2014 the target tab is closed or no sim is connected (check \`peach list\`, reopen with \`peach open\`)`;
|
|
@@ -766,13 +765,18 @@ async function inspectCaptureReady(bridge, timeoutMs) {
|
|
|
766
765
|
if (snapshot.ready) return snapshot;
|
|
767
766
|
return inspectWaitReady(bridge, timeoutMs);
|
|
768
767
|
}
|
|
769
|
-
var READY_SNAPSHOT_SEND_TIMEOUT_MS =
|
|
768
|
+
var READY_SNAPSHOT_SEND_TIMEOUT_MS = 15e3;
|
|
770
769
|
async function inspectReadySnapshot(bridge, budgetMs, simId) {
|
|
771
770
|
const deadline = Date.now() + budgetMs;
|
|
772
771
|
let result;
|
|
773
772
|
do {
|
|
774
|
-
|
|
775
|
-
|
|
773
|
+
const remaining = Math.max(0, deadline - Date.now());
|
|
774
|
+
const sendTimeoutMs = Math.max(
|
|
775
|
+
READY_SNAPSHOT_SEND_TIMEOUT_MS,
|
|
776
|
+
Math.min(remaining, 6e4)
|
|
777
|
+
);
|
|
778
|
+
result = await sendReadyWait(bridge, 1, sendTimeoutMs, simId);
|
|
779
|
+
} while (result.polls !== 1 && !result.error?.startsWith("sim disconnected") && !result.error?.startsWith("bridge never reconnected") && Date.now() < deadline);
|
|
776
780
|
return waitReadyStatus(
|
|
777
781
|
result,
|
|
778
782
|
result.polls === 1 && result.probe ? readyProbeIsReady(result.probe) : false
|
|
@@ -1416,6 +1420,17 @@ async function resolveTargetCoords(bridge, target) {
|
|
|
1416
1420
|
}
|
|
1417
1421
|
|
|
1418
1422
|
// cli/commands/inspect/settling.ts
|
|
1423
|
+
var RuntimeReadinessUnsupportedError = class extends Error {
|
|
1424
|
+
constructor(runtimeVersion, missingFields) {
|
|
1425
|
+
super(
|
|
1426
|
+
`runtime ${runtimeVersion} cannot report animation readiness (${missingFields.join(", ")} missing); run \`peach upgrade\` and reopen the simulator`
|
|
1427
|
+
);
|
|
1428
|
+
this.runtimeVersion = runtimeVersion;
|
|
1429
|
+
this.missingFields = missingFields;
|
|
1430
|
+
__publicField(this, "code", "runtime_readiness_unsupported");
|
|
1431
|
+
this.name = "RuntimeReadinessUnsupportedError";
|
|
1432
|
+
}
|
|
1433
|
+
};
|
|
1419
1434
|
async function waitForSootsimIdle({
|
|
1420
1435
|
bridge,
|
|
1421
1436
|
simId,
|
|
@@ -1425,16 +1440,23 @@ async function waitForSootsimIdle({
|
|
|
1425
1440
|
strict = false,
|
|
1426
1441
|
paintStill = false
|
|
1427
1442
|
}) {
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1443
|
+
let result;
|
|
1444
|
+
try {
|
|
1445
|
+
result = await bridge.send(
|
|
1446
|
+
{
|
|
1447
|
+
type: "evaluate",
|
|
1448
|
+
simId,
|
|
1449
|
+
code: `(async () => {
|
|
1433
1450
|
const start = Date.now()
|
|
1434
1451
|
const deadline = start + ${Math.max(0, Math.round(maxMs))}
|
|
1435
1452
|
const pollMs = ${Math.max(1, Math.round(pollMs))}
|
|
1436
1453
|
const strict = ${strict ? "true" : "false"}
|
|
1437
1454
|
const paintStill = ${paintStill ? "true" : "false"}
|
|
1455
|
+
// full mounted-geometry observation needs at least two hierarchy reads
|
|
1456
|
+
// plus the stillness window, which a sub-second budget cannot afford:
|
|
1457
|
+
// tight budgets (auto-wait) settle on worker stillness plus root
|
|
1458
|
+
// membership, generous ones confirm the geometry too.
|
|
1459
|
+
const fullGeometry = ${maxMs >= 1e3 ? "true" : "false"}
|
|
1438
1460
|
const requiredStillMs = paintStill ? 0 : ${Math.max(1, Math.round(stablePolls)) * Math.max(1, Math.round(pollMs))}
|
|
1439
1461
|
const minimumStablePolls = paintStill ? 1 : ${Math.min(2, Math.max(1, Math.round(stablePolls)))}
|
|
1440
1462
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
@@ -1471,58 +1493,177 @@ async function waitForSootsimIdle({
|
|
|
1471
1493
|
}
|
|
1472
1494
|
} catch {}
|
|
1473
1495
|
|
|
1496
|
+
// a worker that cannot answer within the remaining budget is busy, not
|
|
1497
|
+
// idle: its poll reads as unsettled. bounding each read by the budget
|
|
1498
|
+
// keeps a busy worker from holding a poll past the deadline.
|
|
1499
|
+
const BUSY = { busy: true }
|
|
1500
|
+
const answer = (read) =>
|
|
1501
|
+
Promise.race([
|
|
1502
|
+
Promise.resolve().then(read),
|
|
1503
|
+
new Promise((resolve) =>
|
|
1504
|
+
setTimeout(() => resolve(BUSY), Math.max(deadline - Date.now(), 100)),
|
|
1505
|
+
),
|
|
1506
|
+
])
|
|
1507
|
+
|
|
1474
1508
|
const readSnapshot = async () => {
|
|
1475
1509
|
let animating = false
|
|
1476
1510
|
let layoutDirty = false
|
|
1477
1511
|
let pendingFetches = 0
|
|
1512
|
+
let workerBusy = false
|
|
1478
1513
|
let requestTotal = 0
|
|
1479
1514
|
let requestInFlight = 0
|
|
1515
|
+
let appCommits = null
|
|
1516
|
+
let nodeCount = null
|
|
1480
1517
|
let renderStatsAvailable = false
|
|
1481
1518
|
let shellAnimating = false
|
|
1519
|
+
let webViewStarting = false
|
|
1520
|
+
let webViewBlocker = ''
|
|
1482
1521
|
// strict also waits out shell motion: a system alert, sheet or menu
|
|
1483
1522
|
// animates in the shell worker while the app's own stats read still,
|
|
1484
1523
|
// so its presentation is complete only once the shell's list empties.
|
|
1485
1524
|
if (strict) {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
} catch {}
|
|
1525
|
+
const motion = await answer(() => window.__sootsimTest?.listAnimations?.()).catch(() => null)
|
|
1526
|
+
if (motion === BUSY) workerBusy = true
|
|
1527
|
+
else shellAnimating = Array.isArray(motion) && motion.some((anim) => anim.realm === 'shell' && anim.priority !== 'low')
|
|
1490
1528
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
? stats.memory.imageLoader.pendingFetches
|
|
1507
|
-
: 0
|
|
1508
|
-
pendingFetches = typeof pf === 'number' ? pf : 0
|
|
1529
|
+
const stats = await answer(() => window.__sootsimRenderHost?.queryStats?.()).catch(() => null)
|
|
1530
|
+
if (stats === BUSY) {
|
|
1531
|
+
workerBusy = true
|
|
1532
|
+
} else if (stats) {
|
|
1533
|
+
renderStatsAvailable = true
|
|
1534
|
+
const missingFields = ['hasActiveBlockingNativeAnimations', 'hasPendingBlockingAnimationFrames']
|
|
1535
|
+
.filter((field) => typeof stats[field] !== 'boolean')
|
|
1536
|
+
if (strict && missingFields.length > 0) {
|
|
1537
|
+
return {
|
|
1538
|
+
runtimeUnsupported: {
|
|
1539
|
+
error: 'runtime_readiness_unsupported',
|
|
1540
|
+
runtimeVersion: window.__sootsimRuntimeVersion || 'unknown',
|
|
1541
|
+
missingFields,
|
|
1542
|
+
},
|
|
1543
|
+
}
|
|
1509
1544
|
}
|
|
1510
|
-
|
|
1545
|
+
// positive checks only: an older runtime without the blocking
|
|
1546
|
+
// fields reads as still, and strict rejects that runtime above
|
|
1547
|
+
// instead of ever settling on unknown motion.
|
|
1548
|
+
animating =
|
|
1549
|
+
stats.hasActiveAnims === true ||
|
|
1550
|
+
stats.hasActiveBlockingNativeAnimations === true ||
|
|
1551
|
+
stats.hasPendingBlockingAnimationFrames === true
|
|
1552
|
+
layoutDirty =
|
|
1553
|
+
stats.layoutDirty === true && stats.renderRequested === true
|
|
1554
|
+
// a freshly-pushed screen showing a skeleton is layout-stable
|
|
1555
|
+
// but not actually settled \u2014 its data/images are still in
|
|
1556
|
+
// flight. treat bounded image-loader fetches as not-idle so
|
|
1557
|
+
// settle waits for real content, capped by the budget.
|
|
1558
|
+
const pf = stats.memory && stats.memory.imageLoader
|
|
1559
|
+
? stats.memory.imageLoader.pendingFetches
|
|
1560
|
+
: 0
|
|
1561
|
+
pendingFetches = typeof pf === 'number' ? pf : 0
|
|
1562
|
+
// tenant layout commits: a screen that keeps committing is still
|
|
1563
|
+
// mounting or remounting, even with no animation flag raised.
|
|
1564
|
+
appCommits = typeof stats.appCommitCount === 'number' ? stats.appCommitCount : null
|
|
1565
|
+
}
|
|
1566
|
+
// image preparation ends in the tenant before the compositor decodes
|
|
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)
|
|
1570
|
+
if (compositor === BUSY) {
|
|
1571
|
+
workerBusy = true
|
|
1572
|
+
} else {
|
|
1573
|
+
pendingFetches += compositor.images.pendingFetches
|
|
1574
|
+
pendingFetches += compositor.imageRealization.pending
|
|
1575
|
+
if (compositor.webViewCaptureSettled === false) {
|
|
1576
|
+
webViewStarting = true
|
|
1577
|
+
webViewBlocker = 'compositor webView capture not settled'
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1511
1580
|
try {
|
|
1512
1581
|
const counts = await window.__sootsimTest?.getRequestCounts?.()
|
|
1513
1582
|
requestTotal = typeof counts?.total === 'number' ? counts.total : 0
|
|
1514
1583
|
requestInFlight = typeof counts?.inFlight === 'number' ? counts.inFlight : 0
|
|
1515
1584
|
} catch {}
|
|
1516
|
-
|
|
1585
|
+
// mounted-root membership: the live node count moves while the tree
|
|
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
|
+
}
|
|
1605
|
+
if (hierarchy === BUSY) {
|
|
1606
|
+
workerBusy = true
|
|
1607
|
+
hierarchy = null
|
|
1608
|
+
} else if (!Array.isArray(hierarchy)) {
|
|
1609
|
+
hierarchy = null
|
|
1610
|
+
}
|
|
1517
1611
|
const nodes = []
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1612
|
+
const PREVIEW_PROGRESS_REGEX = /^(creating webview|loading html|fetching bundle|waiting for first render|starting preview|loading simulator|fetching app code|waiting for native preview|starting design|loading canvas|fetching screens|painting the canvas|waiting for webview|waiting for preview|waiting for canvas|preview stalled)/i
|
|
1613
|
+
const notePreviewProgress = (tid, text) => {
|
|
1614
|
+
if (typeof tid === 'string' && (tid === 'web-preview-progress' || tid.endsWith('-preview-progress'))) {
|
|
1615
|
+
webViewStarting = true
|
|
1616
|
+
if (!webViewBlocker) webViewBlocker = 'preview progress active (' + tid + ')'
|
|
1617
|
+
}
|
|
1618
|
+
if (typeof text === 'string' && PREVIEW_PROGRESS_REGEX.test(text.trim())) {
|
|
1619
|
+
webViewStarting = true
|
|
1620
|
+
if (!webViewBlocker) webViewBlocker = 'webView startup in progress ("' + text.trim() + '")'
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
if (hierarchy) {
|
|
1624
|
+
for (const n of hierarchy) {
|
|
1625
|
+
const layout = n && n.layout
|
|
1626
|
+
if (layout && layout.width > 0) {
|
|
1627
|
+
const abs = (n && (n.absolute || n.absolutePosition)) || layout
|
|
1628
|
+
nodes.push(Math.round(abs.x) + ',' + Math.round(abs.y) + ',' + Math.round(layout.width))
|
|
1629
|
+
}
|
|
1630
|
+
notePreviewProgress(
|
|
1631
|
+
n.testID || n.testId,
|
|
1632
|
+
typeof n.text === 'string' ? n.text : '',
|
|
1633
|
+
)
|
|
1634
|
+
}
|
|
1635
|
+
} else {
|
|
1636
|
+
const root = window.__sootsimRoot
|
|
1637
|
+
if (root) {
|
|
1638
|
+
const walk = (n) => {
|
|
1639
|
+
if (n.layout && n.layout.width > 0) {
|
|
1640
|
+
nodes.push(Math.round(n.layout.x) + ',' + Math.round(n.layout.y) + ',' + Math.round(n.layout.width))
|
|
1641
|
+
}
|
|
1642
|
+
notePreviewProgress(
|
|
1643
|
+
n.testID || n.props?.testID || n.props?.testId,
|
|
1644
|
+
n.textContent || (typeof n.props?.children === 'string' ? n.props.children : ''),
|
|
1645
|
+
)
|
|
1646
|
+
for (const c of n.children || []) walk(c)
|
|
1647
|
+
}
|
|
1648
|
+
walk(root)
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
if (!webViewStarting && typeof document !== 'undefined') {
|
|
1652
|
+
const progressEl = document.querySelector(
|
|
1653
|
+
'[data-testid$="-preview-progress"], [data-testid="web-preview-progress"], [data-testid="ios-preview-progress"], [data-testid="design-preview-progress"]'
|
|
1654
|
+
)
|
|
1655
|
+
if (progressEl) {
|
|
1656
|
+
webViewStarting = true
|
|
1657
|
+
webViewBlocker = 'preview progress element displayed'
|
|
1658
|
+
} else {
|
|
1659
|
+
const unreadyWebView = document.querySelector(
|
|
1660
|
+
'[data-sootsim-webview-loading="true"], [data-sootsim-webview-mode="placeholder"]'
|
|
1661
|
+
)
|
|
1662
|
+
if (unreadyWebView) {
|
|
1663
|
+
webViewStarting = true
|
|
1664
|
+
webViewBlocker = 'webView document still loading'
|
|
1522
1665
|
}
|
|
1523
|
-
for (const c of n.children || []) walk(c)
|
|
1524
1666
|
}
|
|
1525
|
-
walk(root)
|
|
1526
1667
|
}
|
|
1527
1668
|
if (paintStill) {
|
|
1528
1669
|
const canvas = composite.getCanvas()
|
|
@@ -1536,7 +1677,7 @@ async function waitForSootsimIdle({
|
|
|
1536
1677
|
pixelFrameToken = token
|
|
1537
1678
|
}
|
|
1538
1679
|
}
|
|
1539
|
-
return { layout: nodes.join(';'), screenPixels, animating, shellAnimating, layoutDirty, pendingFetches, renderStatsAvailable, requestTotal, requestInFlight }
|
|
1680
|
+
return { layout: nodes.join(';'), screenPixels, animating, shellAnimating, layoutDirty, pendingFetches, workerBusy, webViewStarting, webViewBlocker, renderStatsAvailable, requestTotal, requestInFlight, appCommits, nodeCount }
|
|
1540
1681
|
}
|
|
1541
1682
|
|
|
1542
1683
|
// how long generic background network is allowed to keep us waiting AFTER
|
|
@@ -1554,6 +1695,8 @@ async function waitForSootsimIdle({
|
|
|
1554
1695
|
let lastScreenPixels = null
|
|
1555
1696
|
let screenChangedPolls = 0
|
|
1556
1697
|
let lastRequestTotal = -1
|
|
1698
|
+
let lastAppCommits = null
|
|
1699
|
+
let lastNodeCount = null
|
|
1557
1700
|
let stable = 0
|
|
1558
1701
|
let visuallyStillSince = 0
|
|
1559
1702
|
// counts across the whole budget: a flag that is true on every poll is a
|
|
@@ -1563,6 +1706,7 @@ async function waitForSootsimIdle({
|
|
|
1563
1706
|
let dirtyPolls = 0
|
|
1564
1707
|
let animatingPolls = 0
|
|
1565
1708
|
let layoutChangedPolls = 0
|
|
1709
|
+
let webViewStartingPolls = 0
|
|
1566
1710
|
const screenUnchanged = (pixels) => {
|
|
1567
1711
|
if (!pixels || !lastScreenPixels || pixels.width !== lastScreenPixels.width || pixels.height !== lastScreenPixels.height) return false
|
|
1568
1712
|
if (pixels === lastScreenPixels) return true
|
|
@@ -1573,9 +1717,11 @@ async function waitForSootsimIdle({
|
|
|
1573
1717
|
}
|
|
1574
1718
|
while (Date.now() < deadline) {
|
|
1575
1719
|
const snapshot = await readSnapshot()
|
|
1720
|
+
if (snapshot.runtimeUnsupported) return snapshot.runtimeUnsupported
|
|
1576
1721
|
polls++
|
|
1577
1722
|
if (snapshot.layoutDirty) dirtyPolls++
|
|
1578
1723
|
if (snapshot.animating || snapshot.shellAnimating) animatingPolls++
|
|
1724
|
+
if (snapshot.webViewStarting) webViewStartingPolls++
|
|
1579
1725
|
if (polls > 1 && snapshot.layout !== lastLayout) layoutChangedPolls++
|
|
1580
1726
|
const screenChanged = paintStill && !screenUnchanged(snapshot.screenPixels)
|
|
1581
1727
|
if (polls > 1 && screenChanged) screenChangedPolls++
|
|
@@ -1585,12 +1731,24 @@ async function waitForSootsimIdle({
|
|
|
1585
1731
|
!snapshot.animating &&
|
|
1586
1732
|
!snapshot.shellAnimating &&
|
|
1587
1733
|
!snapshot.layoutDirty)
|
|
1588
|
-
// visually settled: no
|
|
1589
|
-
//
|
|
1734
|
+
// visually settled: no worker motion or layout work, no new layout
|
|
1735
|
+
// commits, a stable mounted node count, no image content loading,
|
|
1736
|
+
// no webview startup in progress, layout unchanged since the last
|
|
1737
|
+
// poll. both modes wait out finite worker motion now; strict
|
|
1738
|
+
// additionally implies the flags through strictOk and adds shell
|
|
1739
|
+
// motion plus the blocking-stats floor. a null count or commit
|
|
1740
|
+
// reading means the runtime does not report it, which reads as
|
|
1741
|
+
// stable the way a missing stats block does.
|
|
1590
1742
|
const visuallyStill =
|
|
1591
1743
|
strictOk &&
|
|
1744
|
+
!snapshot.animating &&
|
|
1745
|
+
!snapshot.layoutDirty &&
|
|
1746
|
+
(snapshot.appCommits === null || lastAppCommits === null || snapshot.appCommits === lastAppCommits) &&
|
|
1747
|
+
(snapshot.nodeCount === null || lastNodeCount === null || snapshot.nodeCount === lastNodeCount) &&
|
|
1592
1748
|
!screenChanged &&
|
|
1593
1749
|
snapshot.pendingFetches === 0 &&
|
|
1750
|
+
!snapshot.workerBusy &&
|
|
1751
|
+
!snapshot.webViewStarting &&
|
|
1594
1752
|
snapshot.layout === lastLayout
|
|
1595
1753
|
// generic network quiet: nothing in flight and no new requests issued.
|
|
1596
1754
|
const networkQuiet =
|
|
@@ -1615,15 +1773,22 @@ async function waitForSootsimIdle({
|
|
|
1615
1773
|
lastLayout = snapshot.layout
|
|
1616
1774
|
lastScreenPixels = snapshot.screenPixels
|
|
1617
1775
|
lastRequestTotal = snapshot.requestTotal
|
|
1776
|
+
lastAppCommits = snapshot.appCommits
|
|
1777
|
+
lastNodeCount = snapshot.nodeCount
|
|
1618
1778
|
await sleep(pollMs)
|
|
1619
1779
|
}
|
|
1620
1780
|
const last = await readSnapshot()
|
|
1781
|
+
if (last.runtimeUnsupported) return last.runtimeUnsupported
|
|
1621
1782
|
const blockers = []
|
|
1622
1783
|
if (strict && !last.renderStatsAvailable) blockers.push('render stats unavailable')
|
|
1623
1784
|
if (last.animating) blockers.push('animations still running')
|
|
1624
1785
|
if (last.shellAnimating) blockers.push('shell animations still running')
|
|
1625
1786
|
if (last.layoutDirty) blockers.push('layout still dirty')
|
|
1787
|
+
if (last.appCommits !== null && lastAppCommits !== null && last.appCommits !== lastAppCommits) blockers.push('layout commits still landing')
|
|
1788
|
+
if (last.nodeCount !== null && lastNodeCount !== null && last.nodeCount !== lastNodeCount) blockers.push('node count still changing')
|
|
1626
1789
|
if (last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
1790
|
+
if (last.workerBusy) blockers.push('a render worker too busy to report')
|
|
1791
|
+
if (last.webViewStarting) blockers.push(last.webViewBlocker || 'webView still starting')
|
|
1627
1792
|
if (last.layout !== lastLayout) blockers.push('layout still changing')
|
|
1628
1793
|
if (paintStill && !last.screenPixels) blockers.push('screen pixels unavailable')
|
|
1629
1794
|
else if (paintStill && !screenUnchanged(last.screenPixels)) blockers.push('screen pixels still changing')
|
|
@@ -1636,17 +1801,31 @@ async function waitForSootsimIdle({
|
|
|
1636
1801
|
blockedBy:
|
|
1637
1802
|
(blockers.length ? blockers.join(', ') : 'unknown') +
|
|
1638
1803
|
' over ' + polls + ' polls (layout changed ' + layoutChangedPolls +
|
|
1639
|
-
'x, layoutDirty ' + dirtyPolls + 'x, animating ' + animatingPolls + 'x, screen changed ' + screenChangedPolls + 'x)',
|
|
1804
|
+
'x, layoutDirty ' + dirtyPolls + 'x, animating ' + animatingPolls + 'x, webViewStarting ' + webViewStartingPolls + 'x, screen changed ' + screenChangedPolls + 'x)',
|
|
1640
1805
|
}
|
|
1641
1806
|
} finally {
|
|
1642
1807
|
unsubscribe?.()
|
|
1643
1808
|
}
|
|
1644
1809
|
})()`
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1810
|
+
},
|
|
1811
|
+
{
|
|
1812
|
+
timeoutMs: Math.max(5e3, maxMs + 2e3)
|
|
1813
|
+
}
|
|
1814
|
+
);
|
|
1815
|
+
} catch (error) {
|
|
1816
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1817
|
+
return {
|
|
1818
|
+
settled: false,
|
|
1819
|
+
elapsed: maxMs,
|
|
1820
|
+
blockedBy: message
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1823
|
+
if (result?.error === "runtime_readiness_unsupported" && typeof result.runtimeVersion === "string" && Array.isArray(result.missingFields) && result.missingFields.every((field) => typeof field === "string")) {
|
|
1824
|
+
throw new RuntimeReadinessUnsupportedError(
|
|
1825
|
+
result.runtimeVersion,
|
|
1826
|
+
result.missingFields
|
|
1827
|
+
);
|
|
1828
|
+
}
|
|
1650
1829
|
const { elapsed, settled, blockedBy } = result ?? {};
|
|
1651
1830
|
return {
|
|
1652
1831
|
elapsed: typeof elapsed === "number" ? elapsed : maxMs,
|
|
@@ -1664,6 +1843,7 @@ async function waitReadyAndSettle(bridge, timeoutMs, options = {}) {
|
|
|
1664
1843
|
});
|
|
1665
1844
|
let idle = null;
|
|
1666
1845
|
for (; ; ) {
|
|
1846
|
+
idle = null;
|
|
1667
1847
|
const ready = await inspectWaitReady(bridge, remaining(), options);
|
|
1668
1848
|
if (!ready.ready) return result(ready, idle);
|
|
1669
1849
|
idle = await waitForSootsimIdle({
|
|
@@ -2164,7 +2344,7 @@ function buildSimOpenUrl(currentUrl, target) {
|
|
|
2164
2344
|
const url = new URL(currentUrl);
|
|
2165
2345
|
for (const param of TARGET_SEARCH_PARAMS) url.searchParams.delete(param);
|
|
2166
2346
|
const pathname = url.pathname.replace(/\/+$/, "") || "/";
|
|
2167
|
-
const prefix = pathname === "/
|
|
2347
|
+
const prefix = pathname === "/__peachsim" || pathname.startsWith("/__peachsim/") ? "/__peachsim" : "";
|
|
2168
2348
|
const normalized = String(target).trim();
|
|
2169
2349
|
if (/^\d+$/.test(normalized)) {
|
|
2170
2350
|
url.pathname = `${prefix}/rn/${normalized}`;
|