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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*!
|
|
1
|
+
/*! peach v0.1.1399 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -35,15 +35,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
35
35
|
));
|
|
36
36
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
37
|
|
|
38
|
-
// cli/internal-child.ts
|
|
39
|
-
var RNX_FORKED_SCRIPT_ENV;
|
|
40
|
-
var init_internal_child = __esm({
|
|
41
|
-
"cli/internal-child.ts"() {
|
|
42
|
-
"use strict";
|
|
43
|
-
RNX_FORKED_SCRIPT_ENV = "PEACH_RUNS_FORKED_SCRIPTS";
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
38
|
// src/backend-origin.ts
|
|
48
39
|
function normalizeHostname(hostname) {
|
|
49
40
|
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
@@ -76,6 +67,15 @@ var init_backend_origin = __esm({
|
|
|
76
67
|
}
|
|
77
68
|
});
|
|
78
69
|
|
|
70
|
+
// cli/internal-child.ts
|
|
71
|
+
var RNX_FORKED_SCRIPT_ENV;
|
|
72
|
+
var init_internal_child = __esm({
|
|
73
|
+
"cli/internal-child.ts"() {
|
|
74
|
+
"use strict";
|
|
75
|
+
RNX_FORKED_SCRIPT_ENV = "PEACH_RUNS_FORKED_SCRIPTS";
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
79
|
// src/is-record.ts
|
|
80
80
|
function isRecord(value) {
|
|
81
81
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -114,7 +114,7 @@ function parseSwiftDistributionManifest(value) {
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
function parseSwiftDistributionLock(value) {
|
|
117
|
-
if (!isRecord(value) || typeof value.id !== "string" || !/^[a-f0-9]{16}$/.test(value.id) || typeof value.release !== "string" || typeof value.wasmSdkId !== "string" || typeof value.wasmSdkUrl !== "string" || typeof value.wasmSdkChecksum !== "string" || typeof value.source !== "string" || !isRecord(value.hosts)) {
|
|
117
|
+
if (!isRecord(value) || typeof value.id !== "string" || !/^[a-f0-9]{16}$/.test(value.id) || typeof value.release !== "string" || typeof value.wasmSdkId !== "string" || typeof value.wasmSdkUrl !== "string" || typeof value.wasmSdkChecksum !== "string" || typeof value.source !== "string" || !isStrings(value.targets) || !isRecord(value.hosts)) {
|
|
118
118
|
throw new Error("invalid Swift distribution lock");
|
|
119
119
|
}
|
|
120
120
|
const hosts = value.hosts;
|
|
@@ -132,6 +132,7 @@ function parseSwiftDistributionLock(value) {
|
|
|
132
132
|
wasmSdkUrl: value.wasmSdkUrl,
|
|
133
133
|
wasmSdkChecksum: value.wasmSdkChecksum,
|
|
134
134
|
source: value.source,
|
|
135
|
+
targets: value.targets,
|
|
135
136
|
hosts: {
|
|
136
137
|
"darwin-arm64": entry("darwin-arm64"),
|
|
137
138
|
"linux-x64": entry("linux-x64"),
|
|
@@ -271,7 +272,10 @@ function swiftImplicitResourcePaths(paths) {
|
|
|
271
272
|
function manifestCalls(manifest, kinds) {
|
|
272
273
|
const code = manifest.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"])\/\/[^\n]*/g, "$1");
|
|
273
274
|
const calls = [];
|
|
274
|
-
const pattern = new RegExp(
|
|
275
|
+
const pattern = new RegExp(
|
|
276
|
+
`(?:\\.(${MANIFEST_DECLARATIONS.join("|")})|\\b(Package))\\s*\\(`,
|
|
277
|
+
"g"
|
|
278
|
+
);
|
|
275
279
|
let match;
|
|
276
280
|
while ((match = pattern.exec(code)) !== null) {
|
|
277
281
|
let depth = 1;
|
|
@@ -301,22 +305,59 @@ function manifestCalls(manifest, kinds) {
|
|
|
301
305
|
}
|
|
302
306
|
i++;
|
|
303
307
|
}
|
|
304
|
-
|
|
305
|
-
|
|
308
|
+
const kind = match[1] ?? match[2];
|
|
309
|
+
if (kinds.includes(kind)) calls.push({ kind, flat, call: code.slice(start, i) });
|
|
310
|
+
else if (kind === "Package") {
|
|
311
|
+
calls.push(...manifestCalls(code.slice(start, i - 1), kinds));
|
|
312
|
+
}
|
|
306
313
|
pattern.lastIndex = i;
|
|
307
314
|
}
|
|
308
315
|
return calls;
|
|
309
316
|
}
|
|
317
|
+
function splitManifestArguments(source) {
|
|
318
|
+
const arguments_ = [];
|
|
319
|
+
let start = 0;
|
|
320
|
+
let parentheses = 0;
|
|
321
|
+
let brackets = 0;
|
|
322
|
+
let braces = 0;
|
|
323
|
+
let inString = false;
|
|
324
|
+
let escaped = false;
|
|
325
|
+
for (let index = 0; index < source.length; index++) {
|
|
326
|
+
const character = source[index];
|
|
327
|
+
if (inString) {
|
|
328
|
+
if (escaped) escaped = false;
|
|
329
|
+
else if (character === "\\") escaped = true;
|
|
330
|
+
else if (character === '"') inString = false;
|
|
331
|
+
} else if (character === '"') inString = true;
|
|
332
|
+
else if (character === "(") parentheses++;
|
|
333
|
+
else if (character === ")") parentheses--;
|
|
334
|
+
else if (character === "[") brackets++;
|
|
335
|
+
else if (character === "]") brackets--;
|
|
336
|
+
else if (character === "{") braces++;
|
|
337
|
+
else if (character === "}") braces--;
|
|
338
|
+
else if (character === "," && parentheses === 0 && brackets === 0 && braces === 0) {
|
|
339
|
+
arguments_.push(source.slice(start, index).trim());
|
|
340
|
+
start = index + 1;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const final = source.slice(start).trim();
|
|
344
|
+
if (final) arguments_.push(final);
|
|
345
|
+
return arguments_;
|
|
346
|
+
}
|
|
310
347
|
function swiftPackageIdentity(url) {
|
|
311
348
|
return (url.split("/").pop() ?? url).replace(/\.git$/, "").toLowerCase();
|
|
312
349
|
}
|
|
313
350
|
function swiftManifestTargets(manifest, resourcePaths = []) {
|
|
314
351
|
const implicitResources = swiftImplicitResourcePaths(resourcePaths);
|
|
315
352
|
const targets = [];
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
353
|
+
const declarations = manifestCalls(manifest, ["executableTarget", "target"]);
|
|
354
|
+
const targetNames = new Set(
|
|
355
|
+
declarations.flatMap(({ flat }) => {
|
|
356
|
+
const name2 = /\bname\s*:\s*"([^"]+)"/.exec(flat)?.[1];
|
|
357
|
+
return name2 ? [name2] : [];
|
|
358
|
+
})
|
|
359
|
+
);
|
|
360
|
+
for (const { kind, flat, call } of declarations) {
|
|
320
361
|
const executable = kind === "executableTarget";
|
|
321
362
|
const name2 = /\bname\s*:\s*"([^"]+)"/.exec(flat)?.[1];
|
|
322
363
|
if (!name2) continue;
|
|
@@ -326,6 +367,12 @@ function swiftManifestTargets(manifest, resourcePaths = []) {
|
|
|
326
367
|
/\.swiftLanguageMode\(\s*\.v(\d+)\s*\)/.exec(call)?.[1] ?? "5"
|
|
327
368
|
);
|
|
328
369
|
const mainActorIsolation = /\.defaultIsolation\(\s*MainActor\.self\s*\)/.test(call);
|
|
370
|
+
const cxxInterop = /\.interoperabilityMode\(\s*\.Cxx\s*\)/.test(
|
|
371
|
+
call.replace(/"(?:\\.|[^"\\])*"/g, "")
|
|
372
|
+
);
|
|
373
|
+
const defines = [
|
|
374
|
+
...call.matchAll(/\.define\(\s*"([A-Za-z_][A-Za-z0-9_]*)"\s*\)/g)
|
|
375
|
+
].map((match) => match[1]);
|
|
329
376
|
const excluded = [
|
|
330
377
|
...(/\bexclude\s*:\s*\[([^\]]*)\]/.exec(flat)?.[1] ?? "").matchAll(/"([^"]+)"/g)
|
|
331
378
|
].map((match) => match[1].replace(/^\.\//, "").replace(/\/+$/, ""));
|
|
@@ -339,20 +386,95 @@ function swiftManifestTargets(manifest, resourcePaths = []) {
|
|
|
339
386
|
return false;
|
|
340
387
|
return true;
|
|
341
388
|
});
|
|
389
|
+
const targetArguments = splitManifestArguments(call.slice(0, -1));
|
|
390
|
+
const dependencyArgument = targetArguments.find(
|
|
391
|
+
(argument) => /^dependencies\s*:/.test(argument)
|
|
392
|
+
);
|
|
393
|
+
const dependencyList = dependencyArgument?.replace(/^dependencies\s*:\s*/, "").trim();
|
|
394
|
+
const dependencyNames = /* @__PURE__ */ new Set();
|
|
395
|
+
if (dependencyList?.startsWith("[") && dependencyList.endsWith("]")) {
|
|
396
|
+
for (const dependency of splitManifestArguments(dependencyList.slice(1, -1))) {
|
|
397
|
+
const dependencyName = /^"([^"]+)"$/.exec(dependency)?.[1] ?? /^\.(?:target|byName)\s*\(\s*name\s*:\s*"([^"]+)"/.exec(dependency)?.[1];
|
|
398
|
+
if (dependencyName && targetNames.has(dependencyName))
|
|
399
|
+
dependencyNames.add(dependencyName);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const dependencies = [...dependencyNames].map((name3) => ({
|
|
403
|
+
kind: "target",
|
|
404
|
+
name: name3
|
|
405
|
+
}));
|
|
342
406
|
targets.push({
|
|
343
407
|
name: name2,
|
|
344
408
|
path: targetPath,
|
|
345
409
|
executable,
|
|
346
410
|
languageMode,
|
|
347
411
|
mainActorIsolation,
|
|
348
|
-
|
|
412
|
+
...cxxInterop ? { cxxInterop: true } : {},
|
|
413
|
+
...defines.length === 0 ? {} : { defines },
|
|
414
|
+
resources,
|
|
415
|
+
...dependencies.length === 0 ? {} : { dependencies },
|
|
416
|
+
...excluded.length === 0 ? {} : { exclude: excluded }
|
|
349
417
|
});
|
|
350
418
|
}
|
|
351
419
|
return targets;
|
|
352
420
|
}
|
|
421
|
+
function swiftManifestCxxLanguageStandard(manifest) {
|
|
422
|
+
const declaration = manifestCalls(manifest, ["Package"])[0];
|
|
423
|
+
if (!declaration) return void 0;
|
|
424
|
+
const code = declaration.flat.replace(/"(?:\\.|[^"\\])*"/g, "");
|
|
425
|
+
return /\bcxxLanguageStandard\s*:\s*\.(\w+)/.exec(code)?.[1];
|
|
426
|
+
}
|
|
427
|
+
function swiftResourceBundles(files2, resourcePaths = []) {
|
|
428
|
+
const manifest = files2["Package.swift"] ?? "";
|
|
429
|
+
const targets = swiftManifestTargets(manifest, resourcePaths).filter(
|
|
430
|
+
(target) => target.resources
|
|
431
|
+
);
|
|
432
|
+
if (targets.length === 0) return [];
|
|
433
|
+
const declaration = manifestCalls(manifest, ["Package"])[0];
|
|
434
|
+
const packageName = declaration && /\bname\s*:\s*"([^"/\\]+)"/.exec(declaration.flat)?.[1];
|
|
435
|
+
if (!packageName)
|
|
436
|
+
throw new Error("swift resource bundles require the original package name");
|
|
437
|
+
return targets.map((target) => ({
|
|
438
|
+
target: target.name,
|
|
439
|
+
sourcePath: target.path,
|
|
440
|
+
path: `${packageName}_${target.name}.bundle`
|
|
441
|
+
}));
|
|
442
|
+
}
|
|
443
|
+
function swiftResourceBundleForFile(bundles, file) {
|
|
444
|
+
let owner;
|
|
445
|
+
for (const bundle of bundles) {
|
|
446
|
+
const prefix = bundle.sourcePath === "." ? "" : `${bundle.sourcePath}/`;
|
|
447
|
+
if (file.startsWith(prefix) && (!owner || bundle.sourcePath.length > owner.sourcePath.length))
|
|
448
|
+
owner = bundle;
|
|
449
|
+
}
|
|
450
|
+
return owner;
|
|
451
|
+
}
|
|
452
|
+
function swiftResourceBundleInfoPlist(bundle) {
|
|
453
|
+
const name2 = bundle.path.split("/").pop().replace(/\.(bundle|framework)$/, "");
|
|
454
|
+
const escaped = name2.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
455
|
+
return `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundleName</key><string>${escaped}</string><key>CFBundlePackageType</key><string>${bundle.path.endsWith(".framework") ? "FMWK" : "BNDL"}</string></dict></plist>`;
|
|
456
|
+
}
|
|
457
|
+
function swiftMetalSourceFiles(files2) {
|
|
458
|
+
const sources = Object.entries(files2).filter(([file]) => file.endsWith(".metal"));
|
|
459
|
+
if (sources.length === 0) return {};
|
|
460
|
+
const targets = swiftManifestTargets(files2["Package.swift"] ?? "");
|
|
461
|
+
return Object.fromEntries(
|
|
462
|
+
sources.filter(([file]) => {
|
|
463
|
+
if (targets.length === 0) return true;
|
|
464
|
+
return targets.some((target) => {
|
|
465
|
+
const prefix = target.path === "." ? "" : `${target.path}/`;
|
|
466
|
+
if (!file.startsWith(prefix)) return false;
|
|
467
|
+
const relative = file.slice(prefix.length);
|
|
468
|
+
return !(target.exclude ?? []).some(
|
|
469
|
+
(excluded) => relative === excluded || relative.startsWith(`${excluded}/`)
|
|
470
|
+
);
|
|
471
|
+
});
|
|
472
|
+
})
|
|
473
|
+
);
|
|
474
|
+
}
|
|
353
475
|
function swiftPackagePartition(manifest, resourcePaths = []) {
|
|
354
476
|
const targets = swiftManifestTargets(manifest, resourcePaths);
|
|
355
|
-
return targets.length === 1 && targets[0].executable && targets[0].path === "." ? [] : targets;
|
|
477
|
+
return targets.length === 1 && targets[0].executable && targets[0].path === "." && targets[0].languageMode === 5 && !targets[0].mainActorIsolation && !targets[0].defines?.length && !targets[0].cxxInterop && !swiftManifestCxxLanguageStandard(manifest) ? [] : targets;
|
|
356
478
|
}
|
|
357
479
|
var MANIFEST_DECLARATIONS;
|
|
358
480
|
var init_swift_package = __esm({
|
|
@@ -373,6 +495,42 @@ var init_swift_package = __esm({
|
|
|
373
495
|
}
|
|
374
496
|
});
|
|
375
497
|
|
|
498
|
+
// src/assetCatalogContract.ts
|
|
499
|
+
var init_assetCatalogContract = __esm({
|
|
500
|
+
"src/assetCatalogContract.ts"() {
|
|
501
|
+
"use strict";
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// src/swiftContract.ts
|
|
506
|
+
function isSwiftResourcePath(value) {
|
|
507
|
+
return typeof value === "string" && value.length <= 4096 && !value.startsWith("/") && !value.includes("\\") && !value.includes("\0") && value.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
508
|
+
}
|
|
509
|
+
function isSwiftBundlePath(value) {
|
|
510
|
+
return typeof value === "string" && (value === "." || isSwiftResourcePath(value) && /\.(bundle|framework)$/.test(value));
|
|
511
|
+
}
|
|
512
|
+
function isSwiftResourceBundles(value) {
|
|
513
|
+
return Array.isArray(value) && value.length <= 128 && value.every(
|
|
514
|
+
(bundle) => typeof bundle === "object" && bundle !== null && typeof bundle.target === "string" && /^[A-Za-z_][A-Za-z0-9_-]*$/.test(bundle.target) && (bundle.sourcePath === "." || isSwiftResourcePath(bundle.sourcePath)) && isSwiftBundlePath(bundle.path)
|
|
515
|
+
) && new Set(value.map((bundle) => bundle.target)).size === value.length && new Set(value.map((bundle) => bundle.path)).size === value.length;
|
|
516
|
+
}
|
|
517
|
+
function isSwiftMetalSources(value) {
|
|
518
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.entries(value).every(
|
|
519
|
+
([file, source]) => file.endsWith(".metal") && isSwiftResourcePath(file) && typeof source === "object" && source !== null && !Array.isArray(source) && "url" in source && typeof source.url === "string" && "sha256" in source && typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256)
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
function isSwiftMetalLibrarySources(value) {
|
|
523
|
+
return isSwiftMetalSources(value) && Object.values(value).every(
|
|
524
|
+
(source) => "bundlePath" in source && isSwiftBundlePath(source.bundlePath)
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
var init_swiftContract = __esm({
|
|
528
|
+
"src/swiftContract.ts"() {
|
|
529
|
+
"use strict";
|
|
530
|
+
init_assetCatalogContract();
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
|
|
376
534
|
// src/swift-compile.ts
|
|
377
535
|
function swiftDistributionAt(root) {
|
|
378
536
|
const file = import_node_path2.default.join(root, SWIFT_DISTRIBUTION_MANIFEST);
|
|
@@ -395,6 +553,7 @@ function swiftModuleInputFiles(root) {
|
|
|
395
553
|
"Package.swift",
|
|
396
554
|
"scripts/contrast-app-Package.swift",
|
|
397
555
|
"scripts/build-distribution.ts",
|
|
556
|
+
"scripts/distribution-clang.ts",
|
|
398
557
|
"scripts/build-distribution-plugins.sh",
|
|
399
558
|
"scripts/build-preview-plugin.sh",
|
|
400
559
|
"toolchain.json"
|
|
@@ -419,6 +578,10 @@ function swiftMacroPlugins(moduleRoot) {
|
|
|
419
578
|
stale: false
|
|
420
579
|
};
|
|
421
580
|
const dir = import_node_path2.default.join(moduleRoot, ".build/host/RnxPreviewMacros");
|
|
581
|
+
const release = JSON.parse(
|
|
582
|
+
(0, import_node_fs2.readFileSync)(import_node_path2.default.join(moduleRoot, "toolchain.json"), "utf8")
|
|
583
|
+
).release;
|
|
584
|
+
const compilerStamp = import_node_path2.default.join(dir, "compiler-release");
|
|
422
585
|
const ext = process.platform === "darwin" ? "dylib" : "so";
|
|
423
586
|
const plugins = [
|
|
424
587
|
{
|
|
@@ -432,12 +595,12 @@ function swiftMacroPlugins(moduleRoot) {
|
|
|
432
595
|
];
|
|
433
596
|
return {
|
|
434
597
|
libraries: plugins.map(({ library }) => library),
|
|
435
|
-
stale: plugins.some(
|
|
598
|
+
stale: !(0, import_node_fs2.existsSync)(compilerStamp) || (0, import_node_fs2.readFileSync)(compilerStamp, "utf8").trim() !== release || plugins.some(
|
|
436
599
|
({ library, source }) => !(0, import_node_fs2.existsSync)(library) || (0, import_node_fs2.statSync)(source).mtimeMs > (0, import_node_fs2.statSync)(library).mtimeMs
|
|
437
600
|
)
|
|
438
601
|
};
|
|
439
602
|
}
|
|
440
|
-
async function ensureMacroPlugins(moduleRoot, toolchainBin) {
|
|
603
|
+
async function ensureMacroPlugins(moduleRoot, toolchainBin, release) {
|
|
441
604
|
const { libraries, stale } = swiftMacroPlugins(moduleRoot);
|
|
442
605
|
if (stale) {
|
|
443
606
|
await run2("sh", [
|
|
@@ -445,6 +608,11 @@ async function ensureMacroPlugins(moduleRoot, toolchainBin) {
|
|
|
445
608
|
toolchainBin,
|
|
446
609
|
libraries[0]
|
|
447
610
|
]);
|
|
611
|
+
(0, import_node_fs2.writeFileSync)(
|
|
612
|
+
import_node_path2.default.join(import_node_path2.default.dirname(libraries[0]), "compiler-release"),
|
|
613
|
+
`${release}
|
|
614
|
+
`
|
|
615
|
+
);
|
|
448
616
|
}
|
|
449
617
|
return libraries;
|
|
450
618
|
}
|
|
@@ -629,7 +797,11 @@ function swiftTargetDependencies(files2, targets) {
|
|
|
629
797
|
const siblings = /* @__PURE__ */ new Map();
|
|
630
798
|
for (const target of targets) {
|
|
631
799
|
const prefix = target.path === "." ? "" : `${target.path}/`;
|
|
632
|
-
const deps =
|
|
800
|
+
const deps = new Set(
|
|
801
|
+
(target.dependencies ?? []).flatMap(
|
|
802
|
+
(dependency) => dependency.kind === "target" && dependency.name !== target.name && names.has(dependency.name) ? [dependency.name] : []
|
|
803
|
+
)
|
|
804
|
+
);
|
|
633
805
|
for (const [file, contents] of Object.entries(files2)) {
|
|
634
806
|
if (file === "Package.swift" || !file.startsWith(prefix)) continue;
|
|
635
807
|
if (targets.some(
|
|
@@ -646,7 +818,7 @@ function swiftTargetDependencies(files2, targets) {
|
|
|
646
818
|
}
|
|
647
819
|
function swiftArtifactHash(input, release, moduleRoot) {
|
|
648
820
|
const hash = (0, import_node_crypto2.createHash)("sha256");
|
|
649
|
-
hash.update(`swift-compile/
|
|
821
|
+
hash.update(`swift-compile/v23
|
|
650
822
|
${release}
|
|
651
823
|
`);
|
|
652
824
|
if (input.oneModule) hash.update("one-module\n");
|
|
@@ -655,6 +827,13 @@ ${release}
|
|
|
655
827
|
hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
|
|
656
828
|
hash.update((0, import_node_crypto2.createHash)("sha256").update(input.files[file]).digest());
|
|
657
829
|
}
|
|
830
|
+
for (const file of Object.keys(input.metalSources ?? {}).sort()) {
|
|
831
|
+
hash.update("metal-source\n");
|
|
832
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
|
|
833
|
+
hash.update(
|
|
834
|
+
(0, import_node_crypto2.createHash)("sha256").update(input.metalSources?.[file] ?? "").digest()
|
|
835
|
+
);
|
|
836
|
+
}
|
|
658
837
|
for (const base of Object.keys(input.resources ?? {}).sort()) {
|
|
659
838
|
hash.update((0, import_node_crypto2.createHash)("sha256").update(base).digest());
|
|
660
839
|
hash.update(
|
|
@@ -672,6 +851,19 @@ ${release}
|
|
|
672
851
|
hash.update("resource-path\n");
|
|
673
852
|
hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
|
|
674
853
|
}
|
|
854
|
+
hash.update(
|
|
855
|
+
JSON.stringify(
|
|
856
|
+
[...input.resourceBundles ?? []].sort((a, b) => a.target.localeCompare(b.target))
|
|
857
|
+
)
|
|
858
|
+
);
|
|
859
|
+
for (const target of Object.keys(input.libraries ?? {}).sort()) {
|
|
860
|
+
hash.update(`library
|
|
861
|
+
${target}
|
|
862
|
+
`);
|
|
863
|
+
hash.update(
|
|
864
|
+
(0, import_node_crypto2.createHash)("sha256").update(input.libraries?.[target] ?? "").digest()
|
|
865
|
+
);
|
|
866
|
+
}
|
|
675
867
|
const targets = compileTargets(input);
|
|
676
868
|
if (targets.length > 0) {
|
|
677
869
|
hash.update(`swift-multi/v${MULTI_MANIFEST_VERSION}
|
|
@@ -707,10 +899,22 @@ function emitSwiftPackageManifest(args) {
|
|
|
707
899
|
if (!executable) throw new Error("swift-compile: no executable target to emit");
|
|
708
900
|
const stanza = (target) => {
|
|
709
901
|
const isolation = target.mainActorIsolation ? " .defaultIsolation(MainActor.self)," : "";
|
|
902
|
+
const interoperability = target.cxxInterop ? " .interoperabilityMode(.Cxx)," : "";
|
|
903
|
+
const defines = (target.defines ?? []).map((name2) => ` .define(${JSON.stringify(name2)}),`).join("");
|
|
710
904
|
const imports = distribution ? `, "-I", ${JSON.stringify(import_node_path2.default.join(moduleRoot, "modules"))}` : "";
|
|
711
|
-
const
|
|
905
|
+
const native = args.native?.get(target.name);
|
|
906
|
+
const nativeImports = (siblings.get(target.name) ?? []).filter((name2) => args.native?.has(name2)).map(
|
|
907
|
+
(name2) => `, "-Xfrontend", "-import-module", "-Xfrontend", ${JSON.stringify(name2)}`
|
|
908
|
+
).join("");
|
|
909
|
+
const header = args.headerDirectory && [...args.native?.values() ?? []].some(
|
|
910
|
+
(value) => value.late.producers.includes(target.name)
|
|
911
|
+
) ? `, "-emit-objc-header-path", ${JSON.stringify(import_node_path2.default.join(args.headerDirectory, `${target.name}-Swift.h`))}` : "";
|
|
912
|
+
const swiftSettings = `swiftSettings: [.swiftLanguageMode(.v${target.languageMode}),${isolation}${interoperability}${defines} .unsafeFlags(["-Osize"${FOUNDATION_IMPLICIT_FLAGS}${oneModule ? ONE_IMPLICIT_FLAGS : ""}${imports}${nativeImports}${header}])]`;
|
|
712
913
|
const deps = [
|
|
713
|
-
...
|
|
914
|
+
...target.executable ? [...args.native?.values() ?? []].map(
|
|
915
|
+
(value) => JSON.stringify(value.late.name)
|
|
916
|
+
) : [],
|
|
917
|
+
...distribution || native ? [] : [
|
|
714
918
|
'.product(name: "SwiftUI", package: "sootsim-swift")',
|
|
715
919
|
...oneModule ? [ONE_PRODUCT] : [],
|
|
716
920
|
...spriteKit ? [SPRITEKIT_PRODUCT] : []
|
|
@@ -731,13 +935,15 @@ function emitSwiftPackageManifest(args) {
|
|
|
731
935
|
"-Xlinker", "--export-if-defined=__main_argc_argv"${library},
|
|
732
936
|
]),
|
|
733
937
|
.unsafeFlags(["-Xlinker", "--strip-all"], .when(configuration: .release)),
|
|
734
|
-
]` :
|
|
938
|
+
]` : args.libraries?.has(target.name) ? `,
|
|
939
|
+
linkerSettings: [.unsafeFlags([${JSON.stringify(args.libraries.get(target.name))}])]` : "";
|
|
735
940
|
return [
|
|
736
941
|
` ${kind}(`,
|
|
737
942
|
` name: "${target.name}",`,
|
|
738
943
|
` dependencies: [${deps}],`,
|
|
739
944
|
` path: "${target.path}",`,
|
|
740
|
-
` ${
|
|
945
|
+
...native ? [` exclude: ${JSON.stringify(native.lateSources)},`] : [],
|
|
946
|
+
` ${native ? "cxxSettings: []" : swiftSettings}${link}`,
|
|
741
947
|
` ),`
|
|
742
948
|
].join("\n");
|
|
743
949
|
};
|
|
@@ -752,7 +958,16 @@ function emitSwiftPackageManifest(args) {
|
|
|
752
958
|
` dependencies: [${distribution ? "" : `.package(path: "${moduleRoot}")`}],`,
|
|
753
959
|
" targets: [",
|
|
754
960
|
...targets.map(stanza),
|
|
755
|
-
|
|
961
|
+
...[...args.native?.entries() ?? []].flatMap(([name2, native]) => [
|
|
962
|
+
` .target(name: ${JSON.stringify(native.late.name)},`,
|
|
963
|
+
` dependencies: ${JSON.stringify([name2, ...native.late.producers])},`,
|
|
964
|
+
` path: ${JSON.stringify(native.path)},`,
|
|
965
|
+
` sources: ${JSON.stringify(native.lateSources)},`,
|
|
966
|
+
` publicHeadersPath: "include",`,
|
|
967
|
+
` cxxSettings: [.unsafeFlags(["-fno-cxx-modules", "-I", ${JSON.stringify(native.includeDirectory)}, "-I", ${JSON.stringify(args.headerDirectory)}])]),`
|
|
968
|
+
]),
|
|
969
|
+
args.cxxLanguageStandard ? ` ],
|
|
970
|
+
cxxLanguageStandard: .${args.cxxLanguageStandard}` : " ]",
|
|
756
971
|
")",
|
|
757
972
|
""
|
|
758
973
|
].join("\n");
|
|
@@ -769,9 +984,10 @@ function syncSwiftTree(base, files2) {
|
|
|
769
984
|
};
|
|
770
985
|
walk2(base);
|
|
771
986
|
for (const [full, contents] of files2) {
|
|
772
|
-
if ((0, import_node_fs2.existsSync)(full) && (0, import_node_fs2.readFileSync)(full, "utf8") === contents)
|
|
987
|
+
if ((0, import_node_fs2.existsSync)(full) && (typeof contents === "string" ? (0, import_node_fs2.readFileSync)(full, "utf8") === contents : (0, import_node_fs2.readFileSync)(full).equals(contents)))
|
|
988
|
+
continue;
|
|
773
989
|
(0, import_node_fs2.mkdirSync)(import_node_path2.default.dirname(full), { recursive: true });
|
|
774
|
-
(0, import_node_fs2.writeFileSync)(full, contents
|
|
990
|
+
(0, import_node_fs2.writeFileSync)(full, contents);
|
|
775
991
|
}
|
|
776
992
|
}
|
|
777
993
|
function splitTopLevel(text3) {
|
|
@@ -815,21 +1031,21 @@ function scanObjCExtensionMembers(source, tokens, records) {
|
|
|
815
1031
|
const masked = swiftCodeMask(source);
|
|
816
1032
|
const found = /* @__PURE__ */ new Map();
|
|
817
1033
|
const member = /\b(func|var)\s+([A-Za-z_]\w*)/g;
|
|
818
|
-
for (const
|
|
819
|
-
const close = closingBrace(source, tokens,
|
|
820
|
-
const body = masked.slice(
|
|
1034
|
+
for (const record4 of records) {
|
|
1035
|
+
const close = closingBrace(source, tokens, record4.open);
|
|
1036
|
+
const body = masked.slice(record4.open, close);
|
|
821
1037
|
member.lastIndex = 0;
|
|
822
1038
|
for (let match = member.exec(body); match; match = member.exec(body)) {
|
|
823
|
-
const at =
|
|
1039
|
+
const at = record4.open + match.index + match[0].indexOf(match[1]);
|
|
824
1040
|
let depth = 0;
|
|
825
1041
|
for (const token of tokens) {
|
|
826
|
-
if (token <=
|
|
1042
|
+
if (token <= record4.open) continue;
|
|
827
1043
|
if (token >= at) break;
|
|
828
1044
|
if (source[token] === "{") depth++;
|
|
829
1045
|
else if (source[token] === "}") depth--;
|
|
830
1046
|
}
|
|
831
1047
|
if (depth > 0) continue;
|
|
832
|
-
const head = masked.slice(
|
|
1048
|
+
const head = masked.slice(record4.open, at);
|
|
833
1049
|
const bound = Math.max(
|
|
834
1050
|
head.lastIndexOf(";"),
|
|
835
1051
|
head.lastIndexOf("{"),
|
|
@@ -840,11 +1056,11 @@ function scanObjCExtensionMembers(source, tokens, records) {
|
|
|
840
1056
|
prefix
|
|
841
1057
|
))
|
|
842
1058
|
continue;
|
|
843
|
-
if (!/@objc\b/.test(prefix) && !/@IBAction\b/.test(prefix) && !
|
|
1059
|
+
if (!/@objc\b/.test(prefix) && !/@IBAction\b/.test(prefix) && !record4.objcMembers)
|
|
844
1060
|
continue;
|
|
845
|
-
const members = found.get(
|
|
1061
|
+
const members = found.get(record4.type) ?? /* @__PURE__ */ new Set();
|
|
846
1062
|
members.add(match[2]);
|
|
847
|
-
found.set(
|
|
1063
|
+
found.set(record4.type, members);
|
|
848
1064
|
}
|
|
849
1065
|
}
|
|
850
1066
|
return found;
|
|
@@ -1816,6 +2032,8 @@ function swiftCodeScan(source) {
|
|
|
1816
2032
|
return { lineStarts: starts, tokens };
|
|
1817
2033
|
}
|
|
1818
2034
|
function writeSwiftProject(layout, input, moduleRoot) {
|
|
2035
|
+
if (input.resourceBundles !== void 0 && !isSwiftResourceBundles(input.resourceBundles))
|
|
2036
|
+
throw new Error("swift compile input has invalid target bundle assignments");
|
|
1819
2037
|
const resourceTargets = swiftManifestTargets(
|
|
1820
2038
|
input.files["Package.swift"] ?? "",
|
|
1821
2039
|
input.resourcePaths
|
|
@@ -1832,6 +2050,80 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
1832
2050
|
}
|
|
1833
2051
|
] : compileTargets(input);
|
|
1834
2052
|
const files2 = /* @__PURE__ */ new Map();
|
|
2053
|
+
const native = /* @__PURE__ */ new Map();
|
|
2054
|
+
const headerDirectory = import_node_path2.default.join(layout.root, ".build", "peach-cxx-headers");
|
|
2055
|
+
for (const target of targets) {
|
|
2056
|
+
const prefix = target.path === "." ? "" : `${target.path}/`;
|
|
2057
|
+
const entries = Object.entries(input.files).filter(
|
|
2058
|
+
([file]) => file.startsWith(prefix) && !targets.some(
|
|
2059
|
+
(candidate) => candidate.name !== target.name && candidate.path !== "." && candidate.path.startsWith(prefix) && file.startsWith(`${candidate.path}/`)
|
|
2060
|
+
)
|
|
2061
|
+
);
|
|
2062
|
+
if (entries.some(([file]) => file.endsWith(".swift"))) continue;
|
|
2063
|
+
const units = entries.filter(([file]) => /\.(?:c|cc|cpp|cxx|m|mm)$/.test(file));
|
|
2064
|
+
if (units.length === 0) continue;
|
|
2065
|
+
const includes = `${prefix}include/`;
|
|
2066
|
+
const consumers = /* @__PURE__ */ new Map();
|
|
2067
|
+
const reverse = /* @__PURE__ */ new Map();
|
|
2068
|
+
for (const [file, contents] of entries) {
|
|
2069
|
+
const producers = /* @__PURE__ */ new Set();
|
|
2070
|
+
const source = contents.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
2071
|
+
for (const match of source.matchAll(/^\s*#\s*include\s*[<"]([^>"]+)[>"]/gm)) {
|
|
2072
|
+
const include = match[1];
|
|
2073
|
+
const producer = /(?:^|\/)([^/]+)-Swift\.h$/.exec(include)?.[1];
|
|
2074
|
+
if (producer && targets.some((value) => value.name === producer))
|
|
2075
|
+
producers.add(producer);
|
|
2076
|
+
const local = [
|
|
2077
|
+
import_node_path2.default.posix.join(import_node_path2.default.posix.dirname(file), include),
|
|
2078
|
+
`${includes}${include}`
|
|
2079
|
+
].find((candidate) => input.files[candidate] !== void 0);
|
|
2080
|
+
if (local) {
|
|
2081
|
+
reverse.set(local, [...reverse.get(local) ?? [], file]);
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
consumers.set(file, producers);
|
|
2085
|
+
}
|
|
2086
|
+
const queue = [...consumers.keys()].filter((file) => consumers.get(file).size > 0);
|
|
2087
|
+
for (let index = 0; index < queue.length; index++) {
|
|
2088
|
+
const file = queue[index];
|
|
2089
|
+
for (const parent of reverse.get(file) ?? []) {
|
|
2090
|
+
const inherited = consumers.get(parent);
|
|
2091
|
+
const before = inherited.size;
|
|
2092
|
+
for (const producer of consumers.get(file)) inherited.add(producer);
|
|
2093
|
+
if (before !== inherited.size) queue.push(parent);
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
const late = units.filter(([file]) => consumers.get(file).size > 0);
|
|
2097
|
+
if (late.length === 0) continue;
|
|
2098
|
+
native.set(target.name, {
|
|
2099
|
+
path: target.path,
|
|
2100
|
+
includeDirectory: import_node_path2.default.join(layout.root, includes),
|
|
2101
|
+
lateSources: late.map(([file]) => file.slice(prefix.length)),
|
|
2102
|
+
late: {
|
|
2103
|
+
name: `${target.name}SwiftImplementation`,
|
|
2104
|
+
producers: [
|
|
2105
|
+
...new Set(late.flatMap(([file]) => [...consumers.get(file)]))
|
|
2106
|
+
].sort()
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
if (input.files[`${includes}module.modulemap`] !== void 0) continue;
|
|
2110
|
+
const roots = entries.filter(
|
|
2111
|
+
([file]) => file.startsWith(includes) && /\.(?:h|hpp|hh|hxx)$/.test(file) && consumers.get(file).size === 0
|
|
2112
|
+
);
|
|
2113
|
+
files2.set(
|
|
2114
|
+
import_node_path2.default.join(layout.root, includes, "module.modulemap"),
|
|
2115
|
+
[
|
|
2116
|
+
`module ${target.name} {`,
|
|
2117
|
+
...roots.map(
|
|
2118
|
+
([file]) => ` header ${JSON.stringify(file.slice(includes.length))}`
|
|
2119
|
+
),
|
|
2120
|
+
" export *",
|
|
2121
|
+
"}",
|
|
2122
|
+
""
|
|
2123
|
+
].join("\n")
|
|
2124
|
+
);
|
|
2125
|
+
}
|
|
2126
|
+
if (native.size > 0) (0, import_node_fs2.mkdirSync)(headerDirectory, { recursive: true });
|
|
1835
2127
|
const modulePlan = (0, import_node_crypto2.createHash)("sha256").update(
|
|
1836
2128
|
swiftModuleInputFiles(moduleRoot).join("\n")
|
|
1837
2129
|
);
|
|
@@ -1840,7 +2132,11 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
1840
2132
|
}
|
|
1841
2133
|
const resourcePlan = (0, import_node_crypto2.createHash)("sha256").update(
|
|
1842
2134
|
JSON.stringify(
|
|
1843
|
-
resourceTargets.filter((target) => target.resources).map((target) => [
|
|
2135
|
+
resourceTargets.filter((target) => target.resources).map((target) => [
|
|
2136
|
+
target.name,
|
|
2137
|
+
target.path,
|
|
2138
|
+
input.resourceBundles?.find((bundle) => bundle.target === target.name)?.path
|
|
2139
|
+
])
|
|
1844
2140
|
)
|
|
1845
2141
|
).digest("hex").slice(0, 16);
|
|
1846
2142
|
const moduleFiles = `
|
|
@@ -1900,6 +2196,12 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
1900
2196
|
files2.set(import_node_path2.default.join(layout.root, "Package.swift"), manifest + moduleFiles);
|
|
1901
2197
|
} else {
|
|
1902
2198
|
const base = layout.multi ? layout.root : layout.sources;
|
|
2199
|
+
const libraries = /* @__PURE__ */ new Map();
|
|
2200
|
+
for (const [target, data] of Object.entries(input.libraries ?? {})) {
|
|
2201
|
+
const file = import_node_path2.default.join(layout.root, ".peach-libraries", `lib${target}.a`);
|
|
2202
|
+
files2.set(file, Buffer.from(data, "base64"));
|
|
2203
|
+
libraries.set(target, file);
|
|
2204
|
+
}
|
|
1903
2205
|
for (const [file, contents] of Object.entries(input.files)) {
|
|
1904
2206
|
if (file === "Package.swift") continue;
|
|
1905
2207
|
files2.set(
|
|
@@ -1911,6 +2213,11 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
1911
2213
|
import_node_path2.default.join(layout.root, "Package.swift"),
|
|
1912
2214
|
emitSwiftPackageManifest({
|
|
1913
2215
|
targets,
|
|
2216
|
+
native,
|
|
2217
|
+
headerDirectory: native.size > 0 ? headerDirectory : void 0,
|
|
2218
|
+
cxxLanguageStandard: swiftManifestCxxLanguageStandard(
|
|
2219
|
+
input.files["Package.swift"] ?? ""
|
|
2220
|
+
),
|
|
1914
2221
|
siblings: swiftTargetDependencies(
|
|
1915
2222
|
input.files,
|
|
1916
2223
|
layout.multi ? targets : targets.map((target) => ({ ...target, path: "." }))
|
|
@@ -1918,12 +2225,20 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
1918
2225
|
moduleRoot,
|
|
1919
2226
|
oneModule: input.oneModule,
|
|
1920
2227
|
spriteKit: importsSpriteKit(input.files),
|
|
1921
|
-
distribution: distribution ?? void 0
|
|
2228
|
+
distribution: distribution ?? void 0,
|
|
2229
|
+
libraries
|
|
1922
2230
|
}) + moduleFiles
|
|
1923
2231
|
);
|
|
1924
2232
|
}
|
|
1925
2233
|
for (const target of resourceTargets) {
|
|
1926
2234
|
if (!target.resources) continue;
|
|
2235
|
+
const bundle = input.resourceBundles?.find(
|
|
2236
|
+
(candidate) => candidate.target === target.name
|
|
2237
|
+
);
|
|
2238
|
+
if (!bundle || bundle.sourcePath !== target.path)
|
|
2239
|
+
throw new Error(
|
|
2240
|
+
`swift resource target ${target.name} has no matching bundle assignment`
|
|
2241
|
+
);
|
|
1927
2242
|
const directory = layout.multi ? import_node_path2.default.join(layout.root, target.path) : layout.sources;
|
|
1928
2243
|
files2.set(
|
|
1929
2244
|
import_node_path2.default.join(directory, "ResourceBundleAccessor.generated.swift"),
|
|
@@ -1931,7 +2246,11 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
1931
2246
|
"import Foundation",
|
|
1932
2247
|
"",
|
|
1933
2248
|
"extension Foundation.Bundle {",
|
|
1934
|
-
" static let module: Bundle = Bundle.main"
|
|
2249
|
+
bundle.path === "." ? " static let module: Bundle = Bundle.main" : ` static let module: Bundle = {
|
|
2250
|
+
let url = Bundle.main.bundleURL.appendingPathComponent(${JSON.stringify(bundle.path)})
|
|
2251
|
+
guard let bundle = Bundle(url: url) else { fatalError("resource bundle is missing: ${bundle.target}") }
|
|
2252
|
+
return bundle
|
|
2253
|
+
}()`,
|
|
1935
2254
|
"}",
|
|
1936
2255
|
""
|
|
1937
2256
|
].join("\n")
|
|
@@ -1996,7 +2315,7 @@ function compileSwiftProjectUnit(input, options) {
|
|
|
1996
2315
|
};
|
|
1997
2316
|
const hash = swiftArtifactHash(input, options.release, moduleRoot);
|
|
1998
2317
|
return serialize(root, async () => {
|
|
1999
|
-
if (process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" &&
|
|
2318
|
+
if (process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && moduleRoot === import_node_path2.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
|
|
2000
2319
|
const requestRoot = (0, import_node_fs2.mkdtempSync)(import_node_path2.default.join(root, ".builder-request-"));
|
|
2001
2320
|
const output = import_node_path2.default.join(requestRoot, "output");
|
|
2002
2321
|
const request = import_node_path2.default.join(requestRoot, "request.json");
|
|
@@ -2021,7 +2340,11 @@ function compileSwiftProjectUnit(input, options) {
|
|
|
2021
2340
|
"--output",
|
|
2022
2341
|
output
|
|
2023
2342
|
],
|
|
2024
|
-
{
|
|
2343
|
+
{
|
|
2344
|
+
cwd: repo,
|
|
2345
|
+
timeout: options.timeoutMs,
|
|
2346
|
+
maxBuffer: 64 * 1024 * 1024
|
|
2347
|
+
}
|
|
2025
2348
|
);
|
|
2026
2349
|
pending.child.stdout?.on("data", (bytes2) => process.stdout.write(bytes2));
|
|
2027
2350
|
pending.child.stderr?.on("data", (bytes2) => process.stderr.write(bytes2));
|
|
@@ -2053,7 +2376,11 @@ function compileSwiftProjectUnit(input, options) {
|
|
|
2053
2376
|
`swift-compile: no swift.org toolchain at ${options.toolchainBin}; install ${options.release} and its matching wasm sdk`
|
|
2054
2377
|
);
|
|
2055
2378
|
}
|
|
2056
|
-
const macroPlugins = await ensureMacroPlugins(
|
|
2379
|
+
const macroPlugins = await ensureMacroPlugins(
|
|
2380
|
+
moduleRoot,
|
|
2381
|
+
options.toolchainBin,
|
|
2382
|
+
options.release
|
|
2383
|
+
);
|
|
2057
2384
|
const sdk = swiftModuleSdk(moduleRoot).wasmSdkId;
|
|
2058
2385
|
const icu = swiftIcuAsset(options.toolchainBin, sdk);
|
|
2059
2386
|
try {
|
|
@@ -2061,6 +2388,8 @@ function compileSwiftProjectUnit(input, options) {
|
|
|
2061
2388
|
swift,
|
|
2062
2389
|
[
|
|
2063
2390
|
"build",
|
|
2391
|
+
"--build-system",
|
|
2392
|
+
"native",
|
|
2064
2393
|
"-j",
|
|
2065
2394
|
BUILD_JOBS,
|
|
2066
2395
|
"--package-path",
|
|
@@ -2119,6 +2448,7 @@ var init_swift_compile = __esm({
|
|
|
2119
2448
|
init_swift_distribution_contract();
|
|
2120
2449
|
init_swift_icu();
|
|
2121
2450
|
init_swift_package();
|
|
2451
|
+
init_swiftContract();
|
|
2122
2452
|
run2 = (0, import_node_util2.promisify)(import_node_child_process3.execFile);
|
|
2123
2453
|
WASM_TRIPLE = "wasm32-unknown-wasip1";
|
|
2124
2454
|
cores = import_node_os.default.availableParallelism();
|
|
@@ -2141,6 +2471,7 @@ var init_swift_compile = __esm({
|
|
|
2141
2471
|
TikTokBusinessSDK: [],
|
|
2142
2472
|
nSure: [],
|
|
2143
2473
|
Statsig: [],
|
|
2474
|
+
TOCropViewController: [],
|
|
2144
2475
|
RiveRuntime: ["MetalKit"],
|
|
2145
2476
|
MetalKit: [],
|
|
2146
2477
|
DatadogCore: [],
|
|
@@ -2155,6 +2486,7 @@ var init_swift_compile = __esm({
|
|
|
2155
2486
|
Intercom: [],
|
|
2156
2487
|
FirebaseCore: [],
|
|
2157
2488
|
FirebaseSharedSwift: ["FirebaseCore"],
|
|
2489
|
+
FirebaseRemoteConfig: ["FirebaseCore", "FirebaseSharedSwift"],
|
|
2158
2490
|
FirebaseFirestoreInternal: ["FirebaseCore"],
|
|
2159
2491
|
FirebaseAnalytics: ["FirebaseCore"],
|
|
2160
2492
|
FirebaseAppCheck: ["FirebaseCore"],
|
|
@@ -2162,6 +2494,7 @@ var init_swift_compile = __esm({
|
|
|
2162
2494
|
FirebaseCrashlytics: ["FirebaseCore"],
|
|
2163
2495
|
FirebaseFirestore: ["FirebaseCore", "FirebaseSharedSwift", "FirebaseFirestoreInternal"],
|
|
2164
2496
|
FirebaseStorage: ["FirebaseCore"],
|
|
2497
|
+
GoogleMobileAds: [],
|
|
2165
2498
|
FBAudienceNetwork: []
|
|
2166
2499
|
};
|
|
2167
2500
|
OPTIONAL_FRAMEWORKS = new Set(Object.keys(OPTIONAL_FRAMEWORK_DEPENDENCIES));
|
|
@@ -2177,14 +2510,14 @@ var init_swift_compile = __esm({
|
|
|
2177
2510
|
"PeachObjC",
|
|
2178
2511
|
"Dispatch",
|
|
2179
2512
|
"FoundationNetworking",
|
|
2180
|
-
"
|
|
2181
|
-
"
|
|
2513
|
+
"PeachFoundationCombine",
|
|
2514
|
+
"Darwin"
|
|
2182
2515
|
];
|
|
2183
2516
|
FOUNDATION_IMPLICIT_FLAGS = FOUNDATION_IMPLICIT_MODULES.map(
|
|
2184
2517
|
(module2) => `, "-Xfrontend", "-import-module", "-Xfrontend", "${module2}"`
|
|
2185
2518
|
).join("");
|
|
2186
2519
|
ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"';
|
|
2187
|
-
MULTI_MANIFEST_VERSION =
|
|
2520
|
+
MULTI_MANIFEST_VERSION = 18;
|
|
2188
2521
|
DIRECTIVE = /^[ \t]*#(?:if|elseif)\b/;
|
|
2189
2522
|
OS_IOS = /\bos\(\s*iOS\s*\)/g;
|
|
2190
2523
|
OBJC_ATTRIBUTE = /^@(?:objcMembers\b|objc\b(?:(\s*)\(([^()]*)\))?|IBAction\b)/;
|
|
@@ -2372,24 +2705,135 @@ var swift_distribution_lock_default;
|
|
|
2372
2705
|
var init_swift_distribution_lock = __esm({
|
|
2373
2706
|
"src/swift-distribution.lock.json"() {
|
|
2374
2707
|
swift_distribution_lock_default = {
|
|
2375
|
-
id: "
|
|
2376
|
-
release: "swift-6.
|
|
2377
|
-
wasmSdkId: "swift-6.
|
|
2378
|
-
wasmSdkUrl: "https://r2.
|
|
2379
|
-
wasmSdkChecksum: "
|
|
2380
|
-
source: "
|
|
2708
|
+
id: "3246f7e5ccb24952",
|
|
2709
|
+
release: "swift-6.4.0-RELEASE",
|
|
2710
|
+
wasmSdkId: "swift-6.4.0-RELEASE_wasm-peach-e4629014",
|
|
2711
|
+
wasmSdkUrl: "https://r2.sootsim.com/swift-wasm-sdk/swift-6.4.0-RELEASE_wasm-peach-e4629014.artifactbundle.tar.gz",
|
|
2712
|
+
wasmSdkChecksum: "522f3ff98e951872d64751376d45e36394e572ec2aa4e0a52fb0027824bf41f6",
|
|
2713
|
+
source: "a1e87668019272a329f6d9fada213573e3c5107f",
|
|
2714
|
+
targets: [
|
|
2715
|
+
"ExpoModulesCore",
|
|
2716
|
+
"PeachJSON",
|
|
2717
|
+
"PeachFoundation",
|
|
2718
|
+
"FoundationNetworking",
|
|
2719
|
+
"DeveloperToolsSupport",
|
|
2720
|
+
"SwiftUI",
|
|
2721
|
+
"Dispatch",
|
|
2722
|
+
"Darwin",
|
|
2723
|
+
"MachO",
|
|
2724
|
+
"ObjectiveC",
|
|
2725
|
+
"PeachObjC",
|
|
2726
|
+
"UIKitCore",
|
|
2727
|
+
"PeachICU",
|
|
2728
|
+
"CoreImage",
|
|
2729
|
+
"QuartzCore",
|
|
2730
|
+
"CoreGraphics",
|
|
2731
|
+
"AppTrackingTransparency",
|
|
2732
|
+
"StoreKit",
|
|
2733
|
+
"WeatherKit",
|
|
2734
|
+
"DeviceCheck",
|
|
2735
|
+
"PassKit",
|
|
2736
|
+
"Translation",
|
|
2737
|
+
"CoreSpotlight",
|
|
2738
|
+
"CoreVideo",
|
|
2739
|
+
"CoreMedia",
|
|
2740
|
+
"VideoToolbox",
|
|
2741
|
+
"AdSupport",
|
|
2742
|
+
"BackgroundTasks",
|
|
2743
|
+
"LocalAuthentication",
|
|
2744
|
+
"CoreMotion",
|
|
2745
|
+
"MessageUI",
|
|
2746
|
+
"GameController",
|
|
2747
|
+
"MetricKit",
|
|
2748
|
+
"Metal",
|
|
2749
|
+
"AuthenticationServices",
|
|
2750
|
+
"os",
|
|
2751
|
+
"Charts",
|
|
2752
|
+
"Symbols",
|
|
2753
|
+
"UniformTypeIdentifiers",
|
|
2754
|
+
"WidgetKit",
|
|
2755
|
+
"ActivityKit",
|
|
2756
|
+
"SwiftData",
|
|
2757
|
+
"UIKit",
|
|
2758
|
+
"Combine",
|
|
2759
|
+
"PeachFoundationCombine",
|
|
2760
|
+
"AppIntents",
|
|
2761
|
+
"PhotosUI",
|
|
2762
|
+
"AVFoundation",
|
|
2763
|
+
"AVFAudio",
|
|
2764
|
+
"UserNotifications",
|
|
2765
|
+
"Network",
|
|
2766
|
+
"OSLog",
|
|
2767
|
+
"Security",
|
|
2768
|
+
"Accelerate",
|
|
2769
|
+
"CoreText",
|
|
2770
|
+
"CommonCrypto",
|
|
2771
|
+
"PeachCodec",
|
|
2772
|
+
"Compression",
|
|
2773
|
+
"zlib",
|
|
2774
|
+
"CryptoKit",
|
|
2775
|
+
"TikTokBusinessSDK",
|
|
2776
|
+
"nSure",
|
|
2777
|
+
"Statsig",
|
|
2778
|
+
"TOCropViewController",
|
|
2779
|
+
"RiveRuntime",
|
|
2780
|
+
"MetalKit",
|
|
2781
|
+
"DatadogCore",
|
|
2782
|
+
"DatadogLogs",
|
|
2783
|
+
"DatadogRUM",
|
|
2784
|
+
"DatadogTrace",
|
|
2785
|
+
"AppLovinSDK",
|
|
2786
|
+
"GoogleMobileAds",
|
|
2787
|
+
"AppsFlyerLib",
|
|
2788
|
+
"FBSDKCoreKit",
|
|
2789
|
+
"FBAEMKit",
|
|
2790
|
+
"FBSDKCoreKit_Basics",
|
|
2791
|
+
"FirebaseCore",
|
|
2792
|
+
"FirebaseSharedSwift",
|
|
2793
|
+
"FirebaseRemoteConfig",
|
|
2794
|
+
"FirebaseFirestoreInternal",
|
|
2795
|
+
"FirebaseAnalytics",
|
|
2796
|
+
"FirebaseAppCheck",
|
|
2797
|
+
"FirebaseAuth",
|
|
2798
|
+
"FirebaseCrashlytics",
|
|
2799
|
+
"FirebaseFirestore",
|
|
2800
|
+
"FirebaseStorage",
|
|
2801
|
+
"Intercom",
|
|
2802
|
+
"FBAudienceNetwork",
|
|
2803
|
+
"NaturalLanguage",
|
|
2804
|
+
"AVKit",
|
|
2805
|
+
"SafariServices",
|
|
2806
|
+
"QuickLook",
|
|
2807
|
+
"CoreHaptics",
|
|
2808
|
+
"WebKit",
|
|
2809
|
+
"Photos",
|
|
2810
|
+
"LinkPresentation",
|
|
2811
|
+
"FoundationModels",
|
|
2812
|
+
"CoreTransferable",
|
|
2813
|
+
"AudioToolbox",
|
|
2814
|
+
"Intents",
|
|
2815
|
+
"MobileCoreServices",
|
|
2816
|
+
"ImageIO",
|
|
2817
|
+
"CoreLocationEnums",
|
|
2818
|
+
"CoreLocation",
|
|
2819
|
+
"MapKit",
|
|
2820
|
+
"One",
|
|
2821
|
+
"GameplayKit",
|
|
2822
|
+
"SpriteKit",
|
|
2823
|
+
"PeachBox2D"
|
|
2824
|
+
],
|
|
2381
2825
|
hosts: {
|
|
2382
2826
|
"darwin-arm64": {
|
|
2383
|
-
sha256: "
|
|
2384
|
-
size:
|
|
2827
|
+
sha256: "fb5a3e9db1eae670b5ba84432345e52de8b55b5fdf0e468ff95dfa25a62a6968",
|
|
2828
|
+
size: 55050821
|
|
2385
2829
|
},
|
|
2386
2830
|
"linux-x64": {
|
|
2387
|
-
sha256: "
|
|
2388
|
-
size:
|
|
2831
|
+
sha256: "46a0eae68905751ee7c6536e79f626bc71d9d5a22cf9a76ce12b8d6c3aa34293",
|
|
2832
|
+
size: 55056198
|
|
2389
2833
|
},
|
|
2390
2834
|
"linux-arm64": {
|
|
2391
|
-
sha256: "
|
|
2392
|
-
size:
|
|
2835
|
+
sha256: "ea6453b55ff428d4d152d829731504400d49969ab0750264a931eaf0d7659122",
|
|
2836
|
+
size: 55055213
|
|
2393
2837
|
}
|
|
2394
2838
|
}
|
|
2395
2839
|
};
|
|
@@ -2397,6 +2841,9 @@ var init_swift_distribution_lock = __esm({
|
|
|
2397
2841
|
});
|
|
2398
2842
|
|
|
2399
2843
|
// src/swift-toolchain.ts
|
|
2844
|
+
function swiftCompilerRelease(release) {
|
|
2845
|
+
return release.replace(/^swift-(\d+\.\d+)\.0-RELEASE$/, "swift-$1-RELEASE");
|
|
2846
|
+
}
|
|
2400
2847
|
function swiftToolchainBin(release) {
|
|
2401
2848
|
if (process.platform === "darwin") {
|
|
2402
2849
|
const dirs = [import_node_os4.default.homedir(), "/"].map(
|
|
@@ -2420,7 +2867,7 @@ function swiftToolchain(release, sdk) {
|
|
|
2420
2867
|
encoding: "utf8",
|
|
2421
2868
|
stdio: ["ignore", "pipe", "pipe"]
|
|
2422
2869
|
}) : "";
|
|
2423
|
-
if (!version.includes(`(${release})`)) {
|
|
2870
|
+
if (!version.includes(`(${swiftCompilerRelease(release)})`)) {
|
|
2424
2871
|
const found = version ? `found ${version.split("\n")[0]?.trim()} at ${swift}` : process.platform === "darwin" ? `found no ${release}.xctoolchain in ~/Library/Developer/Toolchains or /Library/Developer/Toolchains` : "found no swift on PATH";
|
|
2425
2872
|
throw new Error(
|
|
2426
2873
|
`peach compiles Swift with the swift.org toolchain ${release} and its wasm SDK; ${found}.
|
|
@@ -2518,12 +2965,15 @@ function swiftDistributionRoot() {
|
|
|
2518
2965
|
}
|
|
2519
2966
|
return pending;
|
|
2520
2967
|
}
|
|
2521
|
-
async function resolveSwiftModule(
|
|
2968
|
+
async function resolveSwiftModule({
|
|
2969
|
+
required = false
|
|
2970
|
+
} = {}) {
|
|
2522
2971
|
const checkout2 = import_node_path6.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift");
|
|
2523
2972
|
if (import_node_fs5.default.existsSync(import_node_path6.default.join(checkout2, "toolchain.json"))) {
|
|
2524
2973
|
try {
|
|
2525
2974
|
return { root: checkout2, ...swiftModuleToolchain(checkout2) };
|
|
2526
|
-
} catch {
|
|
2975
|
+
} catch (error) {
|
|
2976
|
+
if (required) throw error;
|
|
2527
2977
|
return null;
|
|
2528
2978
|
}
|
|
2529
2979
|
}
|
|
@@ -2563,20 +3013,20 @@ function baseOf(file) {
|
|
|
2563
3013
|
const slash = file.lastIndexOf("/");
|
|
2564
3014
|
return slash < 0 ? file : file.slice(slash + 1);
|
|
2565
3015
|
}
|
|
2566
|
-
function
|
|
2567
|
-
|
|
2568
|
-
(
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
};
|
|
3016
|
+
function imagesetFiles(images) {
|
|
3017
|
+
return images.flatMap((image) => {
|
|
3018
|
+
if (typeof image.filename !== "string" || !RASTER_EXTENSIONS.has(extOf(image.filename)) || image.filename.includes("/") || image.filename.includes("\\"))
|
|
3019
|
+
return [];
|
|
3020
|
+
return [
|
|
3021
|
+
{
|
|
3022
|
+
filename: image.filename,
|
|
3023
|
+
scale: image.scale === "2x" ? 2 : image.scale === "3x" ? 3 : 1
|
|
3024
|
+
}
|
|
3025
|
+
];
|
|
3026
|
+
}).sort((a, b) => a.scale - b.scale);
|
|
2577
3027
|
}
|
|
2578
|
-
function flatScale(
|
|
2579
|
-
const match = /@([23])x\.[^./]+$/.exec(
|
|
3028
|
+
function flatScale(path18) {
|
|
3029
|
+
const match = /@([23])x\.[^./]+$/.exec(path18);
|
|
2580
3030
|
return match ? Number(match[1]) : 1;
|
|
2581
3031
|
}
|
|
2582
3032
|
function providesNamespace(text3) {
|
|
@@ -2603,16 +3053,26 @@ function catalogEntryName(contentsPath, kind, readText) {
|
|
|
2603
3053
|
}
|
|
2604
3054
|
return segments.join("/");
|
|
2605
3055
|
}
|
|
2606
|
-
function isFlatResourceImage(
|
|
2607
|
-
return
|
|
3056
|
+
function isFlatResourceImage(path18) {
|
|
3057
|
+
return path18.split("/").includes("Resources") && RASTER_EXTENSIONS.has(extOf(path18));
|
|
2608
3058
|
}
|
|
2609
|
-
function enumerateBundleImages(paths, readText) {
|
|
3059
|
+
function enumerateBundleImages(paths, readText, bundleForFile = () => ".") {
|
|
2610
3060
|
const table = [];
|
|
2611
|
-
const seen = /* @__PURE__ */ new
|
|
2612
|
-
const
|
|
3061
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3062
|
+
const namesFor = (file) => {
|
|
3063
|
+
const bundlePath = bundleForFile(file);
|
|
3064
|
+
if (!isSwiftBundlePath(bundlePath))
|
|
3065
|
+
throw new Error(`invalid image bundle ${bundlePath}`);
|
|
3066
|
+
const names = seen.get(bundlePath) ?? /* @__PURE__ */ new Set();
|
|
3067
|
+
seen.set(bundlePath, names);
|
|
3068
|
+
return { bundlePath, names };
|
|
3069
|
+
};
|
|
3070
|
+
const catalogs = paths.filter((path18) => baseOf(path18) === "Contents.json");
|
|
2613
3071
|
for (const contentsPath of catalogs) {
|
|
2614
3072
|
const name2 = catalogEntryName(contentsPath, ".imageset", readText);
|
|
2615
|
-
if (name2 === null
|
|
3073
|
+
if (name2 === null) continue;
|
|
3074
|
+
const { bundlePath, names } = namesFor(contentsPath);
|
|
3075
|
+
if (names.has(name2)) continue;
|
|
2616
3076
|
let parsed;
|
|
2617
3077
|
try {
|
|
2618
3078
|
const text3 = readText(contentsPath);
|
|
@@ -2624,18 +3084,24 @@ function enumerateBundleImages(paths, readText) {
|
|
|
2624
3084
|
const images = parsed?.images;
|
|
2625
3085
|
if (!Array.isArray(images)) continue;
|
|
2626
3086
|
const dir = contentsPath.split("/").slice(0, -1).join("/");
|
|
2627
|
-
const
|
|
2628
|
-
if (
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
3087
|
+
const variants = imagesetFiles(images);
|
|
3088
|
+
if (variants.length === 0) continue;
|
|
3089
|
+
names.add(name2);
|
|
3090
|
+
for (const variant of variants)
|
|
3091
|
+
table.push({
|
|
3092
|
+
name: name2,
|
|
3093
|
+
file: `${dir}/${variant.filename}`,
|
|
3094
|
+
scale: variant.scale,
|
|
3095
|
+
bundlePath
|
|
3096
|
+
});
|
|
2632
3097
|
}
|
|
2633
|
-
for (const
|
|
2634
|
-
if (!isFlatResourceImage(
|
|
2635
|
-
const name2 = baseOf(
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
3098
|
+
for (const path18 of paths) {
|
|
3099
|
+
if (!isFlatResourceImage(path18)) continue;
|
|
3100
|
+
const name2 = baseOf(path18).slice(0, -extOf(path18).length);
|
|
3101
|
+
const { bundlePath, names } = namesFor(path18);
|
|
3102
|
+
if (name2 === "" || names.has(name2)) continue;
|
|
3103
|
+
names.add(name2);
|
|
3104
|
+
table.push({ name: name2, file: path18, scale: flatScale(path18), bundlePath });
|
|
2639
3105
|
}
|
|
2640
3106
|
return table;
|
|
2641
3107
|
}
|
|
@@ -2664,7 +3130,7 @@ function colorsetValue(color) {
|
|
|
2664
3130
|
}
|
|
2665
3131
|
function enumerateBundleColors(paths, readText) {
|
|
2666
3132
|
const table = {};
|
|
2667
|
-
for (const contentsPath of paths.filter((
|
|
3133
|
+
for (const contentsPath of paths.filter((path18) => baseOf(path18) === "Contents.json")) {
|
|
2668
3134
|
const name2 = catalogEntryName(contentsPath, ".colorset", readText);
|
|
2669
3135
|
if (name2 === null || name2 in table) continue;
|
|
2670
3136
|
let colors;
|
|
@@ -2728,8 +3194,8 @@ function axisExtremes(points) {
|
|
|
2728
3194
|
function pathBounds(d) {
|
|
2729
3195
|
const xs = [];
|
|
2730
3196
|
const ys = [];
|
|
2731
|
-
for (const
|
|
2732
|
-
(0, import_svgpath.default)(
|
|
3197
|
+
for (const path18 of d)
|
|
3198
|
+
(0, import_svgpath.default)(path18).abs().unshort().unarc().iterate((segment2, _index, x, y) => {
|
|
2733
3199
|
const [command, ...args] = segment2;
|
|
2734
3200
|
if (command === "M" || command === "L") {
|
|
2735
3201
|
xs.push(Number(args[0]));
|
|
@@ -2754,11 +3220,14 @@ function guide(svg, id, axis) {
|
|
|
2754
3220
|
const value = line === void 0 ? void 0 : new RegExp(`${axis}="([-0-9.]+)"`).exec(line)?.[1];
|
|
2755
3221
|
return value === void 0 ? null : Number(value);
|
|
2756
3222
|
}
|
|
2757
|
-
function enumerateBundleSymbols(paths, readText) {
|
|
3223
|
+
function enumerateBundleSymbols(paths, readText, bundleForFile) {
|
|
2758
3224
|
const table = {};
|
|
2759
|
-
for (const contentsPath of paths.filter((
|
|
3225
|
+
for (const contentsPath of paths.filter((path18) => baseOf(path18) === "Contents.json")) {
|
|
2760
3226
|
const name2 = catalogEntryName(contentsPath, ".symbolset", readText);
|
|
2761
|
-
if (name2 === null
|
|
3227
|
+
if (name2 === null) continue;
|
|
3228
|
+
const bundle = bundleForFile(contentsPath);
|
|
3229
|
+
const key2 = bundle === "." ? name2 : `${bundle}/${name2}`;
|
|
3230
|
+
if (Object.hasOwn(table, key2)) continue;
|
|
2762
3231
|
let symbols;
|
|
2763
3232
|
try {
|
|
2764
3233
|
symbols = Reflect.get(JSON.parse(readText(contentsPath) ?? "null") ?? {}, "symbols");
|
|
@@ -2785,22 +3254,27 @@ function enumerateBundleSymbols(paths, readText) {
|
|
|
2785
3254
|
const translateY = 12 - (box.minY + box.maxY) * scale / 2;
|
|
2786
3255
|
const advance = Math.round((right - left) * scale * 1e3) / 1e3;
|
|
2787
3256
|
const tall = (box.maxY - box.minY) * scale + 0.175 * 24;
|
|
2788
|
-
table[
|
|
3257
|
+
table[key2] = {
|
|
2789
3258
|
viewBox: "0 0 24 24",
|
|
2790
3259
|
advance,
|
|
2791
3260
|
box: [12 - advance / 2, 12 - tall / 2, advance, tall],
|
|
2792
|
-
layers: d.map((
|
|
2793
|
-
d: (0, import_svgpath.default)(
|
|
3261
|
+
layers: d.map((path18) => ({
|
|
3262
|
+
d: (0, import_svgpath.default)(path18).abs().scale(scale).translate(translateX, translateY).round(3).toString()
|
|
2794
3263
|
}))
|
|
2795
3264
|
};
|
|
2796
3265
|
}
|
|
2797
3266
|
return table;
|
|
2798
3267
|
}
|
|
2799
|
-
function
|
|
3268
|
+
function isCopiedResource(path18) {
|
|
3269
|
+
const ext = extOf(path18);
|
|
3270
|
+
if (ext === ".json" || ext === ".xcstrings") return true;
|
|
3271
|
+
return !RASTER_EXTENSIONS.has(ext) && !COMPILED_EXTENSIONS.has(ext) && !path18.split("/").some((segment2) => NESTED_BUNDLE_DIR.test(segment2));
|
|
3272
|
+
}
|
|
3273
|
+
function enumerateBundleResources(paths) {
|
|
2800
3274
|
const found = [];
|
|
2801
3275
|
const seen = /* @__PURE__ */ new Set();
|
|
2802
3276
|
const ordered = [...paths].filter(
|
|
2803
|
-
(
|
|
3277
|
+
(path18) => path18.split("/").includes("Resources") && path18.split("/").every((segment2) => segment2 !== "" && segment2 !== "..") && isCopiedResource(path18)
|
|
2804
3278
|
).sort((a, b) => {
|
|
2805
3279
|
const aDepth = a.split("/").length;
|
|
2806
3280
|
const bDepth = b.split("/").length;
|
|
@@ -2814,11 +3288,13 @@ function enumerateBundleJson(paths) {
|
|
|
2814
3288
|
}
|
|
2815
3289
|
return found;
|
|
2816
3290
|
}
|
|
2817
|
-
var import_svgpath, RASTER_EXTENSIONS, SYMBOL_CAP_HEIGHT_EM;
|
|
3291
|
+
var import_svgpath, RASTER_EXTENSIONS, SYMBOL_CAP_HEIGHT_EM, COMPILED_EXTENSIONS, NESTED_BUNDLE_DIR;
|
|
2818
3292
|
var init_bundleAssets = __esm({
|
|
2819
3293
|
"../sootsim-swift/src/bundleAssets.ts"() {
|
|
2820
3294
|
"use strict";
|
|
2821
3295
|
import_svgpath = __toESM(require("svgpath"), 1);
|
|
3296
|
+
init_assetCatalogContract();
|
|
3297
|
+
init_swiftContract();
|
|
2822
3298
|
RASTER_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
2823
3299
|
".avif",
|
|
2824
3300
|
".bmp",
|
|
@@ -2830,6 +3306,8 @@ var init_bundleAssets = __esm({
|
|
|
2830
3306
|
".webp"
|
|
2831
3307
|
]);
|
|
2832
3308
|
SYMBOL_CAP_HEIGHT_EM = 1443 / 2048;
|
|
3309
|
+
COMPILED_EXTENSIONS = /* @__PURE__ */ new Set([".swift", ".metal", ".storyboard", ".xib"]);
|
|
3310
|
+
NESTED_BUNDLE_DIR = /\.(?:xcassets|lproj)$/;
|
|
2833
3311
|
}
|
|
2834
3312
|
});
|
|
2835
3313
|
|
|
@@ -3316,7 +3794,7 @@ function frameworkModules(paths) {
|
|
|
3316
3794
|
}
|
|
3317
3795
|
async function range(url, spec) {
|
|
3318
3796
|
const response = await fetch(url, {
|
|
3319
|
-
headers: { range: `bytes=${spec}
|
|
3797
|
+
headers: { range: `bytes=${spec}`, "accept-encoding": "identity" },
|
|
3320
3798
|
signal: AbortSignal.timeout(2e4)
|
|
3321
3799
|
});
|
|
3322
3800
|
const match = /^bytes (\d+)-\d+\/(\d+)$/.exec(
|
|
@@ -3345,9 +3823,9 @@ async function zipEntries(url) {
|
|
|
3345
3823
|
if (locator < 0 || tail.bytes.readUInt32LE(locator) !== 117853008)
|
|
3346
3824
|
throw new Error(`${url} has no zip64 locator`);
|
|
3347
3825
|
const recordAt = Number(tail.bytes.readBigUInt64LE(locator + 8));
|
|
3348
|
-
const
|
|
3349
|
-
size = Number(
|
|
3350
|
-
offset = Number(
|
|
3826
|
+
const record4 = recordAt >= tail.start ? tail.bytes.subarray(recordAt - tail.start) : (await range(url, `${recordAt}-${recordAt + 55}`)).bytes;
|
|
3827
|
+
size = Number(record4.readBigUInt64LE(40));
|
|
3828
|
+
offset = Number(record4.readBigUInt64LE(48));
|
|
3351
3829
|
}
|
|
3352
3830
|
const directory = offset >= tail.start ? tail.bytes.subarray(offset - tail.start, offset - tail.start + size) : (await range(url, `${offset}-${offset + size - 1}`)).bytes;
|
|
3353
3831
|
const names = [];
|
|
@@ -3405,7 +3883,7 @@ function dump(dir) {
|
|
|
3405
3883
|
).digest("hex").slice(0, 32);
|
|
3406
3884
|
const cached2 = import_node_path9.default.join(cacheDir2, `${key2}.json`);
|
|
3407
3885
|
if (import_node_fs8.default.existsSync(cached2))
|
|
3408
|
-
return { key: key2, raw:
|
|
3886
|
+
return { key: key2, raw: record3(JSON.parse(import_node_fs8.default.readFileSync(cached2, "utf8"))) };
|
|
3409
3887
|
let output;
|
|
3410
3888
|
try {
|
|
3411
3889
|
output = (0, import_node_child_process6.execFileSync)(
|
|
@@ -3434,13 +3912,13 @@ function dump(dir) {
|
|
|
3434
3912
|
}
|
|
3435
3913
|
import_node_fs8.default.mkdirSync(cacheDir2, { recursive: true });
|
|
3436
3914
|
import_node_fs8.default.writeFileSync(cached2, output);
|
|
3437
|
-
return { key: key2, raw:
|
|
3915
|
+
return { key: key2, raw: record3(JSON.parse(output)) };
|
|
3438
3916
|
}
|
|
3439
3917
|
function defaultTraits(manifest) {
|
|
3440
3918
|
const traits = new Map(
|
|
3441
3919
|
array(manifest.traits).map((trait) => [
|
|
3442
|
-
string(
|
|
3443
|
-
array(
|
|
3920
|
+
string(record3(trait).name) ?? "",
|
|
3921
|
+
array(record3(trait).enabledTraits).flatMap((name2) => string(name2) ?? [])
|
|
3444
3922
|
])
|
|
3445
3923
|
);
|
|
3446
3924
|
const enabled = /* @__PURE__ */ new Set();
|
|
@@ -3454,7 +3932,7 @@ function defaultTraits(manifest) {
|
|
|
3454
3932
|
return enabled;
|
|
3455
3933
|
}
|
|
3456
3934
|
function linksOnIOS(condition, traits) {
|
|
3457
|
-
const { platformNames, traits: needed } =
|
|
3935
|
+
const { platformNames, traits: needed } = record3(condition);
|
|
3458
3936
|
const platforms = array(platformNames);
|
|
3459
3937
|
if (platforms.length > 0 && !platforms.includes("ios")) return false;
|
|
3460
3938
|
const gates = array(needed);
|
|
@@ -3467,7 +3945,7 @@ function swiftPackageManifest(dir) {
|
|
|
3467
3945
|
if (known) return known;
|
|
3468
3946
|
const traits = defaultTraits(raw2);
|
|
3469
3947
|
const tools = Number(
|
|
3470
|
-
/^(\d+)/.exec(string(
|
|
3948
|
+
/^(\d+)/.exec(string(record3(raw2.toolsVersion)._version) ?? "5")?.[1] ?? 5
|
|
3471
3949
|
);
|
|
3472
3950
|
const declaredModes = array(raw2.swiftLanguageVersions).flatMap((mode) => {
|
|
3473
3951
|
const major = Number(/^(\d+)/.exec(string(mode) ?? "")?.[1]);
|
|
@@ -3479,11 +3957,11 @@ function swiftPackageManifest(dir) {
|
|
|
3479
3957
|
);
|
|
3480
3958
|
const packages = /* @__PURE__ */ new Map();
|
|
3481
3959
|
for (const entry of array(raw2.dependencies)) {
|
|
3482
|
-
const { sourceControl, fileSystem } =
|
|
3483
|
-
const source =
|
|
3960
|
+
const { sourceControl, fileSystem } = record3(entry);
|
|
3961
|
+
const source = record3(array(sourceControl ?? fileSystem)[0]);
|
|
3484
3962
|
const identity = string(source.identity);
|
|
3485
3963
|
if (!identity) continue;
|
|
3486
|
-
const url = string(
|
|
3964
|
+
const url = string(record3(array(record3(source.location).remote)[0]).urlString);
|
|
3487
3965
|
const local = string(source.path);
|
|
3488
3966
|
const value = url ? { url } : local ? { dir: local } : null;
|
|
3489
3967
|
if (!value) continue;
|
|
@@ -3493,26 +3971,26 @@ function swiftPackageManifest(dir) {
|
|
|
3493
3971
|
}
|
|
3494
3972
|
const products = /* @__PURE__ */ new Map();
|
|
3495
3973
|
for (const product of array(raw2.products)) {
|
|
3496
|
-
const { name:
|
|
3497
|
-
if (!string(
|
|
3974
|
+
const { name: name3, targets: targets2, type } = record3(product);
|
|
3975
|
+
if (!string(name3) || !("library" in record3(type))) continue;
|
|
3498
3976
|
products.set(
|
|
3499
|
-
string(
|
|
3977
|
+
string(name3),
|
|
3500
3978
|
array(targets2).flatMap((target) => string(target) ?? [])
|
|
3501
3979
|
);
|
|
3502
3980
|
}
|
|
3503
3981
|
const targets = /* @__PURE__ */ new Map();
|
|
3504
|
-
const names = new Set(array(raw2.targets).map((target) => string(
|
|
3982
|
+
const names = new Set(array(raw2.targets).map((target) => string(record3(target).name)));
|
|
3505
3983
|
for (const entry of array(raw2.targets)) {
|
|
3506
|
-
const target =
|
|
3507
|
-
const
|
|
3984
|
+
const target = record3(entry);
|
|
3985
|
+
const name3 = string(target.name);
|
|
3508
3986
|
const kind = string(target.type);
|
|
3509
|
-
if (!
|
|
3987
|
+
if (!name3 || !isTargetType(kind)) continue;
|
|
3510
3988
|
const declared = string(target.path);
|
|
3511
3989
|
const roots = kind === "test" ? ["Tests"] : ["Sources", "Source", "src", "srcs"];
|
|
3512
|
-
const targetDir = declared ? import_node_path9.default.resolve(dir, declared) : roots.map((root) => import_node_path9.default.join(dir, root,
|
|
3990
|
+
const targetDir = declared ? import_node_path9.default.resolve(dir, declared) : roots.map((root) => import_node_path9.default.join(dir, root, name3)).find((candidate) => import_node_fs8.default.existsSync(candidate)) ?? import_node_path9.default.join(dir, roots[0], name3);
|
|
3513
3991
|
const dependencies = [];
|
|
3514
3992
|
for (const dependency of array(target.dependencies)) {
|
|
3515
|
-
const { target: local, product, byName } =
|
|
3993
|
+
const { target: local, product, byName } = record3(dependency);
|
|
3516
3994
|
const payload = array(local ?? product ?? byName);
|
|
3517
3995
|
if (!linksOnIOS(payload[payload.length - 1], traits)) continue;
|
|
3518
3996
|
const dependencyName = string(payload[0]);
|
|
@@ -3534,16 +4012,26 @@ function swiftPackageManifest(dir) {
|
|
|
3534
4012
|
}
|
|
3535
4013
|
let languageMode = packageMode;
|
|
3536
4014
|
let mainActorIsolation = false;
|
|
4015
|
+
const defines = [];
|
|
3537
4016
|
for (const setting of array(target.settings)) {
|
|
3538
|
-
const
|
|
3539
|
-
const
|
|
4017
|
+
const { kind: rawKind, tool, condition } = record3(setting);
|
|
4018
|
+
const settingKind = record3(rawKind);
|
|
4019
|
+
const mode = string(record3(settingKind.swiftLanguageMode)._0);
|
|
3540
4020
|
if (mode)
|
|
3541
4021
|
languageMode = Math.max(5, Number(/^(\d+)/.exec(mode)?.[1] ?? languageMode));
|
|
3542
|
-
if (string(
|
|
4022
|
+
if (string(record3(settingKind.defaultIsolation)._0) === "MainActor")
|
|
3543
4023
|
mainActorIsolation = true;
|
|
4024
|
+
const define = string(record3(settingKind.define)._0);
|
|
4025
|
+
if (define && string(tool) === "swift" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(define) && linksOnIOS(condition, traits)) {
|
|
4026
|
+
const config = string(record3(condition).config);
|
|
4027
|
+
defines.push({
|
|
4028
|
+
name: define,
|
|
4029
|
+
configuration: config === "debug" || config === "release" ? config : null
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
3544
4032
|
}
|
|
3545
|
-
targets.set(
|
|
3546
|
-
name:
|
|
4033
|
+
targets.set(name3, {
|
|
4034
|
+
name: name3,
|
|
3547
4035
|
type: kind,
|
|
3548
4036
|
dir: targetDir,
|
|
3549
4037
|
sources: target.sources == null ? null : array(target.sources).flatMap((file) => string(file) ?? []),
|
|
@@ -3551,12 +4039,15 @@ function swiftPackageManifest(dir) {
|
|
|
3551
4039
|
dependencies,
|
|
3552
4040
|
languageMode,
|
|
3553
4041
|
mainActorIsolation,
|
|
4042
|
+
defines,
|
|
3554
4043
|
declaresResources: array(target.resources).length > 0,
|
|
3555
4044
|
url: string(target.url) ?? null,
|
|
3556
4045
|
checksum: string(target.checksum) ?? null
|
|
3557
4046
|
});
|
|
3558
4047
|
}
|
|
3559
|
-
const
|
|
4048
|
+
const name2 = string(raw2.name);
|
|
4049
|
+
if (!name2) throw new Error(`swiftpm returned no package name for ${dir}`);
|
|
4050
|
+
const manifest = { name: name2, dir, products, targets, packages };
|
|
3560
4051
|
evaluated.set(key2, manifest);
|
|
3561
4052
|
return manifest;
|
|
3562
4053
|
}
|
|
@@ -3582,7 +4073,7 @@ function swiftTargetFiles(manifest, target) {
|
|
|
3582
4073
|
];
|
|
3583
4074
|
return included.flatMap(walk).filter((file) => !within(file, excluded)).sort();
|
|
3584
4075
|
}
|
|
3585
|
-
var import_node_child_process6, import_node_crypto5, import_node_fs8, import_node_os6, import_node_path9, TARGET_TYPES, isTargetType,
|
|
4076
|
+
var import_node_child_process6, import_node_crypto5, import_node_fs8, import_node_os6, import_node_path9, TARGET_TYPES, isTargetType, record3, array, string, cacheDir2, evaluated, within;
|
|
3586
4077
|
var init_swift_package_manifest = __esm({
|
|
3587
4078
|
"src/swift-package-manifest.ts"() {
|
|
3588
4079
|
"use strict";
|
|
@@ -3603,7 +4094,7 @@ var init_swift_package_manifest = __esm({
|
|
|
3603
4094
|
"plugin"
|
|
3604
4095
|
];
|
|
3605
4096
|
isTargetType = (value) => TARGET_TYPES.some((type) => type === value);
|
|
3606
|
-
|
|
4097
|
+
record3 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3607
4098
|
array = (value) => Array.isArray(value) ? value : [];
|
|
3608
4099
|
string = (value) => typeof value === "string" ? value : void 0;
|
|
3609
4100
|
cacheDir2 = import_node_path9.default.join(import_node_os6.default.tmpdir(), "peach-swift-manifests");
|
|
@@ -3726,6 +4217,7 @@ function resolveSwiftPackages(options) {
|
|
|
3726
4217
|
files: files2,
|
|
3727
4218
|
packageDir: pkg.manifest.dir,
|
|
3728
4219
|
remote: pkg.remote,
|
|
4220
|
+
packageDefines: target.defines,
|
|
3729
4221
|
executable: false,
|
|
3730
4222
|
languageMode: target.languageMode,
|
|
3731
4223
|
mainActorIsolation: target.mainActorIsolation,
|
|
@@ -4092,10 +4584,10 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4092
4584
|
owners.push(...physical.map(() => current));
|
|
4093
4585
|
};
|
|
4094
4586
|
const scoped = (body) => (symbol, ...rest) => {
|
|
4095
|
-
const
|
|
4096
|
-
if (omit.has(
|
|
4587
|
+
const path18 = pathOf(symbol);
|
|
4588
|
+
if (omit.has(path18)) return void skipped.push({ path: path18, reason: omit.get(path18) });
|
|
4097
4589
|
const previous = current;
|
|
4098
|
-
current =
|
|
4590
|
+
current = path18;
|
|
4099
4591
|
try {
|
|
4100
4592
|
body(symbol, ...rest);
|
|
4101
4593
|
} finally {
|
|
@@ -4115,14 +4607,14 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4115
4607
|
const access = (symbol, openOwner) => symbol.accessLevel === "open" && openOwner ? "open" : "public";
|
|
4116
4608
|
const emitMember = scoped(
|
|
4117
4609
|
(member, indent, context) => {
|
|
4118
|
-
const
|
|
4610
|
+
const path18 = pathOf(member);
|
|
4119
4611
|
if (TYPE_KINDS.has(member.kind.identifier)) {
|
|
4120
4612
|
emitType(member, indent);
|
|
4121
4613
|
return;
|
|
4122
4614
|
}
|
|
4123
4615
|
if (member.kind.identifier === "swift.enum.case") return;
|
|
4124
4616
|
if (!MEMBER_KINDS.has(member.kind.identifier)) {
|
|
4125
|
-
skipped.push({ path:
|
|
4617
|
+
skipped.push({ path: path18, reason: `unhandled ${member.kind.identifier}` });
|
|
4126
4618
|
return;
|
|
4127
4619
|
}
|
|
4128
4620
|
const { 1: attrs, 2: rest } = LEADING_ATTRS.exec(text(member));
|
|
@@ -4136,12 +4628,12 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4136
4628
|
const final = context.inClass && flags.has("final") ? "final " : "";
|
|
4137
4629
|
const mutating = flags.has("mutating") ? "mutating " : flags.has("nonmutating") ? "nonmutating " : "";
|
|
4138
4630
|
let core = `${flags.has("convenience") ? "convenience " : ""}${modifiers[2]}`;
|
|
4139
|
-
const override = context.inClass && !options.plain?.has(
|
|
4631
|
+
const override = context.inClass && !options.plain?.has(path18) && (flags.has("override") || overrides.has(member.identifier.precise) || options.forcedOverride?.has(path18) || isObjC(member) && path18.endsWith(".init()")) ? "override " : "";
|
|
4140
4632
|
const head = `${indent}${attrs}${access(member, context.openOwner)} ${required ? "required " : ""}${final}${override}${mutating}`;
|
|
4141
|
-
const measured = behavior.get(
|
|
4142
|
-
if (measured) used.add(
|
|
4633
|
+
const measured = behavior.get(path18);
|
|
4634
|
+
if (measured) used.add(path18);
|
|
4143
4635
|
const overloadBody = /\basync\b/.test(core) ? measured?.asyncBody : /\bResult</.test(core) ? measured?.resultBody : void 0;
|
|
4144
|
-
const body = overloadBody ?? measured?.body ?? trap(
|
|
4636
|
+
const body = overloadBody ?? measured?.body ?? trap(path18);
|
|
4145
4637
|
switch (member.kind.identifier) {
|
|
4146
4638
|
case "swift.property":
|
|
4147
4639
|
case "swift.type.property":
|
|
@@ -4162,7 +4654,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4162
4654
|
return;
|
|
4163
4655
|
}
|
|
4164
4656
|
emit(
|
|
4165
|
-
`${head}${computed} { get${effects} { ${body} }${settable && !effects ? ` ${parsed.nonmutating ? "nonmutating " : ""}set { ${measured?.set ?? trap(
|
|
4657
|
+
`${head}${computed} { get${effects} { ${body} }${settable && !effects ? ` ${parsed.nonmutating ? "nonmutating " : ""}set { ${measured?.set ?? trap(path18)} }` : ""} }`
|
|
4166
4658
|
);
|
|
4167
4659
|
return;
|
|
4168
4660
|
}
|
|
@@ -4215,7 +4707,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4215
4707
|
};
|
|
4216
4708
|
const emitType = scoped(
|
|
4217
4709
|
(symbol, indent) => {
|
|
4218
|
-
const
|
|
4710
|
+
const path18 = pathOf(symbol);
|
|
4219
4711
|
const id = symbol.identifier.precise;
|
|
4220
4712
|
const inner = `${indent} `;
|
|
4221
4713
|
switch (symbol.kind.identifier) {
|
|
@@ -4227,10 +4719,10 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4227
4719
|
case "swift.class": {
|
|
4228
4720
|
const shape = header(symbol, "class", indent);
|
|
4229
4721
|
if (!shape)
|
|
4230
|
-
return void skipped.push({ path:
|
|
4231
|
-
const parent = options.superclasses?.get(
|
|
4722
|
+
return void skipped.push({ path: path18, reason: `unparsed class ${text(symbol)}` });
|
|
4723
|
+
const parent = options.superclasses?.get(path18) ?? superclass.get(id);
|
|
4232
4724
|
const blocked = classBlocked(id);
|
|
4233
|
-
if (blocked) return void skipped.push({ path:
|
|
4725
|
+
if (blocked) return void skipped.push({ path: path18, reason: blocked });
|
|
4234
4726
|
const ancestors = /* @__PURE__ */ new Set();
|
|
4235
4727
|
for (let at = superId.get(id); at; at = superId.get(at))
|
|
4236
4728
|
for (const name2 of conforms.get(at) ?? []) ancestors.add(name2);
|
|
@@ -4246,9 +4738,9 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4246
4738
|
`${indent}${shape.attrs}${open ? "open" : "public"} class ${shape.name}${shape.generics}${list2.length ? `: ${list2.join(", ")}` : ""}${selfConforming(shape.where)} {`
|
|
4247
4739
|
);
|
|
4248
4740
|
const members = membersOf(id);
|
|
4249
|
-
const extra = options.behavior?.get(
|
|
4741
|
+
const extra = options.behavior?.get(path18)?.members;
|
|
4250
4742
|
if (extra) {
|
|
4251
|
-
used.add(
|
|
4743
|
+
used.add(path18);
|
|
4252
4744
|
emit(`${inner}${extra}`);
|
|
4253
4745
|
}
|
|
4254
4746
|
for (const member of members)
|
|
@@ -4300,13 +4792,13 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4300
4792
|
continue;
|
|
4301
4793
|
have.add(witnessKey(member));
|
|
4302
4794
|
have.add(sideLeaf(member));
|
|
4303
|
-
emitWitness(member, inner,
|
|
4795
|
+
emitWitness(member, inner, path18);
|
|
4304
4796
|
}
|
|
4305
4797
|
}
|
|
4306
4798
|
const coder = members.some((member) => leaf(member) === "init(coder:)");
|
|
4307
4799
|
if (designated && !coder && externalRoot(id) !== "NSObject" && externalRoot(id) !== null)
|
|
4308
4800
|
emit(
|
|
4309
|
-
`${inner}public required init?(coder: NSCoder) { ${trap(`${
|
|
4801
|
+
`${inner}public required init?(coder: NSCoder) { ${trap(`${path18}.init(coder:)`)} }`
|
|
4310
4802
|
);
|
|
4311
4803
|
emit(`${indent}}`);
|
|
4312
4804
|
return;
|
|
@@ -4314,7 +4806,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4314
4806
|
case "swift.struct": {
|
|
4315
4807
|
const shape = header(symbol, "struct", indent);
|
|
4316
4808
|
if (!shape)
|
|
4317
|
-
return void skipped.push({ path:
|
|
4809
|
+
return void skipped.push({ path: path18, reason: `unparsed struct ${text(symbol)}` });
|
|
4318
4810
|
const members = membersOf(id);
|
|
4319
4811
|
const raw2 = rawType(members);
|
|
4320
4812
|
const list2 = inheritance(id);
|
|
@@ -4346,7 +4838,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4346
4838
|
case "swift.enum": {
|
|
4347
4839
|
const shape = header(symbol, "enum", indent);
|
|
4348
4840
|
if (!shape)
|
|
4349
|
-
return void skipped.push({ path:
|
|
4841
|
+
return void skipped.push({ path: path18, reason: `unparsed enum ${text(symbol)}` });
|
|
4350
4842
|
const members = membersOf(id);
|
|
4351
4843
|
const raw2 = rawType(members);
|
|
4352
4844
|
const cases = members.filter(
|
|
@@ -4355,7 +4847,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4355
4847
|
const missing = raw2 ? cases.filter((member) => !values.has(member.identifier.precise)) : [];
|
|
4356
4848
|
if (raw2 && isObjC(symbol) && missing.length > 0)
|
|
4357
4849
|
return void skipped.push({
|
|
4358
|
-
path:
|
|
4850
|
+
path: path18,
|
|
4359
4851
|
reason: `no header value for ${missing.map(leaf).join(", ")}`
|
|
4360
4852
|
});
|
|
4361
4853
|
const list2 = inheritance(id, raw2 ?? void 0).filter(
|
|
@@ -4395,7 +4887,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4395
4887
|
const shape = header(symbol, "protocol", indent);
|
|
4396
4888
|
if (!shape)
|
|
4397
4889
|
return void skipped.push({
|
|
4398
|
-
path:
|
|
4890
|
+
path: path18,
|
|
4399
4891
|
reason: `unparsed protocol ${text(symbol)}`
|
|
4400
4892
|
});
|
|
4401
4893
|
const list2 = [...isObjC(symbol) ? ["AnyObject"] : [], ...inheritance(id)];
|
|
@@ -4420,7 +4912,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4420
4912
|
}
|
|
4421
4913
|
emit(`${indent}}`);
|
|
4422
4914
|
if (defaults.length > 0) {
|
|
4423
|
-
emit(`${indent}extension ${
|
|
4915
|
+
emit(`${indent}extension ${path18} {`);
|
|
4424
4916
|
for (const member of defaults) {
|
|
4425
4917
|
const decl = text(member);
|
|
4426
4918
|
if (optional.has(member.identifier.precise) && member.kind.identifier === "swift.method" && !decl.replace(/\([^)]*\)/g, "").includes("->") && !/ async\b/.test(decl))
|
|
@@ -4466,7 +4958,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4466
4958
|
return init ? /rawValue:\s*([^)]+)\)/.exec(text(init))?.[1]?.trim() ?? null : null;
|
|
4467
4959
|
};
|
|
4468
4960
|
const emitGlobal = scoped((symbol) => {
|
|
4469
|
-
const
|
|
4961
|
+
const path18 = pathOf(symbol);
|
|
4470
4962
|
const kind = symbol.kind.identifier;
|
|
4471
4963
|
if (kind === "swift.func" || kind === "swift.func.op" || kind === "swift.method" || kind === "swift.type.method") {
|
|
4472
4964
|
const { 1: attrs, 2: rest } = LEADING_ATTRS.exec(text(symbol));
|
|
@@ -4477,17 +4969,17 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4477
4969
|
if (fix && !/^(?:prefix|infix|postfix)\b/.test(spelled))
|
|
4478
4970
|
spelled = `${fix} ${spelled}`;
|
|
4479
4971
|
}
|
|
4480
|
-
emit(`${attrs}public ${spelled} { ${trap(
|
|
4972
|
+
emit(`${attrs}public ${spelled} { ${trap(path18)} }`);
|
|
4481
4973
|
} else if (kind === "swift.var") {
|
|
4482
4974
|
const parsed = splitAccessors(text(symbol).replace(/^let /, "var "));
|
|
4483
|
-
const measured = behavior.get(
|
|
4484
|
-
if (measured) used.add(
|
|
4485
|
-
emit(`public ${parsed.decl} { ${measured?.body ?? trap(
|
|
4486
|
-
} else skipped.push({ path:
|
|
4975
|
+
const measured = behavior.get(path18);
|
|
4976
|
+
if (measured) used.add(path18);
|
|
4977
|
+
emit(`public ${parsed.decl} { ${measured?.body ?? trap(path18)} }`);
|
|
4978
|
+
} else skipped.push({ path: path18, reason: `unhandled top-level ${kind}` });
|
|
4487
4979
|
});
|
|
4488
4980
|
const roots = [...byId.values()].filter((symbol) => !owner.has(symbol.identifier.precise) && !unavailable(symbol)).sort((a, b) => pathOf(a).localeCompare(pathOf(b)));
|
|
4489
4981
|
for (const symbol of roots) {
|
|
4490
|
-
const
|
|
4982
|
+
const path18 = pathOf(symbol);
|
|
4491
4983
|
if (TYPE_KINDS.has(symbol.kind.identifier)) emitType(symbol, "");
|
|
4492
4984
|
else emitGlobal(symbol);
|
|
4493
4985
|
}
|
|
@@ -4519,7 +5011,7 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4519
5011
|
else emitMember(member, " ", { openOwner: false, inClass: false });
|
|
4520
5012
|
emit(`}`);
|
|
4521
5013
|
}
|
|
4522
|
-
const imports = [
|
|
5014
|
+
const imports = [...STANDIN_IMPORTS, ...options.imports ?? []];
|
|
4523
5015
|
const banner = [
|
|
4524
5016
|
`// stand-in for the binary ${options.module} module, generated from ${options.source}.`,
|
|
4525
5017
|
`// do not hand-edit: every body traps because the vendor binary cannot run`,
|
|
@@ -4528,9 +5020,9 @@ function emitSwiftStandin(graphs, options) {
|
|
|
4528
5020
|
...imports.map((name2) => `import ${name2}`),
|
|
4529
5021
|
""
|
|
4530
5022
|
];
|
|
4531
|
-
for (const
|
|
4532
|
-
if (!used.has(
|
|
4533
|
-
skipped.push({ path:
|
|
5023
|
+
for (const path18 of behavior.keys())
|
|
5024
|
+
if (!used.has(path18))
|
|
5025
|
+
skipped.push({ path: path18, reason: "behavior names no emitted declaration" });
|
|
4534
5026
|
return {
|
|
4535
5027
|
source: `${[...banner, ...lines].join("\n")}
|
|
4536
5028
|
`,
|
|
@@ -4566,11 +5058,12 @@ function stripDefaults(decl) {
|
|
|
4566
5058
|
}
|
|
4567
5059
|
return out;
|
|
4568
5060
|
}
|
|
4569
|
-
var STANDIN_EMIT_VERSION, TYPE_KINDS, MEMBER_KINDS, ACCESSOR_WORD, KEEP_EXTERNAL, LEADING_ATTRS, OBJC_ONLY, text, leaf, pathOf, unavailable, witnessKey, sideLeaf, isObjC, synthesizedEquality, trap, KEYWORDS, tick;
|
|
5061
|
+
var STANDIN_EMIT_VERSION, STANDIN_IMPORTS, TYPE_KINDS, MEMBER_KINDS, ACCESSOR_WORD, KEEP_EXTERNAL, LEADING_ATTRS, OBJC_ONLY, text, leaf, pathOf, unavailable, witnessKey, sideLeaf, isObjC, synthesizedEquality, trap, KEYWORDS, tick;
|
|
4570
5062
|
var init_swift_standin_emit = __esm({
|
|
4571
5063
|
"src/swift-standin-emit.ts"() {
|
|
4572
5064
|
"use strict";
|
|
4573
5065
|
STANDIN_EMIT_VERSION = "5";
|
|
5066
|
+
STANDIN_IMPORTS = ["Foundation", "UIKit"];
|
|
4574
5067
|
TYPE_KINDS = /* @__PURE__ */ new Set([
|
|
4575
5068
|
"swift.class",
|
|
4576
5069
|
"swift.struct",
|
|
@@ -4616,7 +5109,7 @@ var init_swift_standin_emit = __esm({
|
|
|
4616
5109
|
sideLeaf = (symbol) => `${symbol.kind.identifier.startsWith("swift.type.") ? "type" : "instance"}|leaf|${leaf(symbol)}`;
|
|
4617
5110
|
isObjC = (symbol) => symbol.identifier.precise.startsWith("c:");
|
|
4618
5111
|
synthesizedEquality = (symbol, conforms) => conforms.includes("Hashable") ? ["==(_:_:)", "hash(into:)", "hashValue"].includes(leaf(symbol)) : conforms.includes("Equatable") && leaf(symbol) === "==(_:_:)";
|
|
4619
|
-
trap = (
|
|
5112
|
+
trap = (path18) => `fatalError("${path18} is a binary framework peach cannot run")`;
|
|
4620
5113
|
KEYWORDS = /* @__PURE__ */ new Set([
|
|
4621
5114
|
"Type",
|
|
4622
5115
|
"Protocol",
|
|
@@ -4768,6 +5261,8 @@ function xcframework(binary) {
|
|
|
4768
5261
|
}
|
|
4769
5262
|
function surfaces(xcframeworkDir) {
|
|
4770
5263
|
const slice = import_node_fs12.default.readdirSync(xcframeworkDir).filter((name2) => /^ios-.+-simulator$/.test(name2)).sort()[0];
|
|
5264
|
+
if (!slice && xcframeworkDir.endsWith(".framework"))
|
|
5265
|
+
throw new Error("a plain .framework has no .xcframework simulator slice");
|
|
4771
5266
|
if (!slice) throw new Error("it has no iOS simulator slice");
|
|
4772
5267
|
const root = import_node_path12.default.join(xcframeworkDir, slice);
|
|
4773
5268
|
const found = [];
|
|
@@ -4810,6 +5305,9 @@ function peachModuleDirs(toolchain, imports) {
|
|
|
4810
5305
|
const { moduleRoot, toolchainBin } = toolchain;
|
|
4811
5306
|
if (swiftDistributionAt(moduleRoot)) return [import_node_path12.default.join(moduleRoot, "modules")];
|
|
4812
5307
|
const peach = new Set(swiftPeachModules(moduleRoot));
|
|
5308
|
+
const targets = [.../* @__PURE__ */ new Set([...STANDIN_IMPORTS, ...imports])].filter(
|
|
5309
|
+
(name2) => peach.has(name2)
|
|
5310
|
+
);
|
|
4813
5311
|
const plugins = swiftMacroPlugins(moduleRoot);
|
|
4814
5312
|
if (plugins.stale)
|
|
4815
5313
|
exec("sh", [
|
|
@@ -4817,11 +5315,15 @@ function peachModuleDirs(toolchain, imports) {
|
|
|
4817
5315
|
toolchainBin,
|
|
4818
5316
|
plugins.libraries[0]
|
|
4819
5317
|
]);
|
|
4820
|
-
for (const target of
|
|
5318
|
+
for (const target of targets)
|
|
4821
5319
|
exec(
|
|
4822
5320
|
import_node_path12.default.join(toolchainBin, "swift"),
|
|
4823
5321
|
[
|
|
4824
5322
|
"build",
|
|
5323
|
+
"--build-system",
|
|
5324
|
+
"native",
|
|
5325
|
+
"-j",
|
|
5326
|
+
"4",
|
|
4825
5327
|
"--swift-sdk",
|
|
4826
5328
|
swiftModuleSdk(moduleRoot).wasmSdkId,
|
|
4827
5329
|
"-c",
|
|
@@ -4848,7 +5350,12 @@ function peachModuleDirs(toolchain, imports) {
|
|
|
4848
5350
|
];
|
|
4849
5351
|
}
|
|
4850
5352
|
function swiftInterfaceForWasm(text3) {
|
|
4851
|
-
|
|
5353
|
+
const rooted = text3.replace(
|
|
5354
|
+
/\bObjectiveC(\.|::)(NSObject|NSObjectProtocol)\b/g,
|
|
5355
|
+
"Foundation$1$2"
|
|
5356
|
+
);
|
|
5357
|
+
const foundation = rooted !== text3 && !/^import[ \t]+Foundation\b/m.test(rooted) ? rooted.replace(/^(?=import[ \t])/m, "import Foundation\n") : rooted;
|
|
5358
|
+
return foundation.replace(
|
|
4852
5359
|
/^(\/\/ swift-module-flags:.*)$/m,
|
|
4853
5360
|
(flags) => flags.replace(/-target \S+/, `-target ${TRIPLE}`).replace(/\s-enable-objc-interop\b/, "").replace(/\s-target-variant \S+/, "")
|
|
4854
5361
|
).replace(
|
|
@@ -5165,6 +5672,158 @@ ${roots.map((file) => ` header "${file}"
|
|
|
5165
5672
|
}
|
|
5166
5673
|
};
|
|
5167
5674
|
}
|
|
5675
|
+
function crateFor(root, name2) {
|
|
5676
|
+
const walk2 = (dir, depth) => {
|
|
5677
|
+
const manifest = import_node_path12.default.join(dir, "Cargo.toml");
|
|
5678
|
+
if (import_node_fs12.default.existsSync(manifest)) {
|
|
5679
|
+
const text3 = import_node_fs12.default.readFileSync(manifest, "utf8");
|
|
5680
|
+
const section = (title) => new RegExp(`^\\[${title}\\]\\s*$([\\s\\S]*?)(?=^\\[|(?![\\s\\S]))`, "m").exec(
|
|
5681
|
+
text3
|
|
5682
|
+
)?.[1] ?? "";
|
|
5683
|
+
const field = (body, key2) => new RegExp(`^${key2}\\s*=\\s*"([^"]+)"`, "m").exec(body)?.[1];
|
|
5684
|
+
const lib = section("lib");
|
|
5685
|
+
const crate = field(lib, "name") ?? field(section("package"), "name")?.replaceAll("-", "_");
|
|
5686
|
+
if (crate === name2) {
|
|
5687
|
+
if (!/crate-type\s*=\s*\[[^\]]*"staticlib"/.test(lib))
|
|
5688
|
+
throw new Error(
|
|
5689
|
+
`${import_node_path12.default.relative(root, manifest)} builds lib${name2} without crate-type "staticlib"`
|
|
5690
|
+
);
|
|
5691
|
+
return manifest;
|
|
5692
|
+
}
|
|
5693
|
+
}
|
|
5694
|
+
if (depth === 0) return null;
|
|
5695
|
+
for (const entry of import_node_fs12.default.readdirSync(dir, { withFileTypes: true })) {
|
|
5696
|
+
if (!entry.isDirectory() || UNSEARCHED.has(entry.name) || entry.name.endsWith(".xcframework"))
|
|
5697
|
+
continue;
|
|
5698
|
+
const found = walk2(import_node_path12.default.join(dir, entry.name), depth - 1);
|
|
5699
|
+
if (found) return found;
|
|
5700
|
+
}
|
|
5701
|
+
return null;
|
|
5702
|
+
};
|
|
5703
|
+
return walk2(root, 4);
|
|
5704
|
+
}
|
|
5705
|
+
function standinLibrary(binary, searchRoot) {
|
|
5706
|
+
const dir = xcframework(binary).dir;
|
|
5707
|
+
const slice = import_node_fs12.default.readdirSync(dir).filter((name2) => /^ios-.+-simulator$/.test(name2)).sort()[0];
|
|
5708
|
+
const library = slice ? import_node_fs12.default.readdirSync(import_node_path12.default.join(dir, slice)).find((name2) => /^lib.+\.a$/.test(name2)) : void 0;
|
|
5709
|
+
const supplied = import_node_path12.default.join(dir, RUST_TARGET);
|
|
5710
|
+
if (import_node_fs12.default.existsSync(supplied)) {
|
|
5711
|
+
const found = import_node_fs12.default.readdirSync(supplied).filter((name2) => name2.endsWith(".a"));
|
|
5712
|
+
const chosen = library && found.includes(library) ? library : found.length === 1 ? found[0] : null;
|
|
5713
|
+
if (!chosen)
|
|
5714
|
+
throw new Error(
|
|
5715
|
+
`${import_node_path12.default.relative(searchRoot, supplied)} holds no single static library${library ? ` named ${library}` : ""}`
|
|
5716
|
+
);
|
|
5717
|
+
return import_node_path12.default.join(supplied, chosen);
|
|
5718
|
+
}
|
|
5719
|
+
if (!library) return null;
|
|
5720
|
+
const manifest = crateFor(searchRoot, library.slice("lib".length, -".a".length));
|
|
5721
|
+
if (!manifest) return null;
|
|
5722
|
+
const result = (0, import_node_child_process8.spawnSync)(
|
|
5723
|
+
"cargo",
|
|
5724
|
+
[
|
|
5725
|
+
"build",
|
|
5726
|
+
"--release",
|
|
5727
|
+
"--target",
|
|
5728
|
+
RUST_TARGET,
|
|
5729
|
+
"--message-format=json-render-diagnostics",
|
|
5730
|
+
"--manifest-path",
|
|
5731
|
+
manifest
|
|
5732
|
+
],
|
|
5733
|
+
{
|
|
5734
|
+
encoding: "utf8",
|
|
5735
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
5736
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5737
|
+
}
|
|
5738
|
+
);
|
|
5739
|
+
const crate = import_node_path12.default.relative(searchRoot, import_node_path12.default.dirname(manifest));
|
|
5740
|
+
if (result.error)
|
|
5741
|
+
throw new Error(
|
|
5742
|
+
`${crate} is a rust crate and cargo is not installed; install rust (https://rustup.rs), then run again`
|
|
5743
|
+
);
|
|
5744
|
+
if (result.status !== 0) {
|
|
5745
|
+
if (/target may not be installed|can't find crate for `(core|std)`/.test(result.stderr))
|
|
5746
|
+
throw new Error(
|
|
5747
|
+
`${crate} builds for ${RUST_TARGET}, which this rust lacks; run \`rustup target add ${RUST_TARGET}\`, then run again`
|
|
5748
|
+
);
|
|
5749
|
+
throw new Error(
|
|
5750
|
+
`cargo could not build ${crate} for ${RUST_TARGET}: ${failure(result)}`
|
|
5751
|
+
);
|
|
5752
|
+
}
|
|
5753
|
+
for (const line of result.stdout.split("\n")) {
|
|
5754
|
+
if (!line.startsWith("{")) continue;
|
|
5755
|
+
const message = JSON.parse(line);
|
|
5756
|
+
if (!message || typeof message !== "object" || !("filenames" in message) || !Array.isArray(message.filenames))
|
|
5757
|
+
continue;
|
|
5758
|
+
const archive = message.filenames.find(
|
|
5759
|
+
(file) => typeof file === "string" && import_node_path12.default.basename(file) === library
|
|
5760
|
+
);
|
|
5761
|
+
if (archive) return archive;
|
|
5762
|
+
}
|
|
5763
|
+
throw new Error(`cargo built ${crate} for ${RUST_TARGET} but reported no ${library}`);
|
|
5764
|
+
}
|
|
5765
|
+
function sourceBinaryStandins(binary, toolchain, provided) {
|
|
5766
|
+
const repo = import_node_path12.default.resolve(toolchain.moduleRoot, "../..");
|
|
5767
|
+
const work = import_node_fs12.default.mkdtempSync(import_node_path12.default.join(import_node_os7.default.tmpdir(), "peach-standin-request-"));
|
|
5768
|
+
try {
|
|
5769
|
+
const artifact = xcframework(binary);
|
|
5770
|
+
const local = { ...binary, dir: artifact.dir, url: null, checksum: null };
|
|
5771
|
+
const generation = standinGenerationInputs([local], toolchain);
|
|
5772
|
+
const request = import_node_path12.default.join(work, "request.json");
|
|
5773
|
+
const delivery = import_node_path12.default.join(work, "delivery");
|
|
5774
|
+
import_node_fs12.default.writeFileSync(
|
|
5775
|
+
request,
|
|
5776
|
+
JSON.stringify({
|
|
5777
|
+
binary: local,
|
|
5778
|
+
provided: [...provided],
|
|
5779
|
+
generation,
|
|
5780
|
+
release: toolchain.release,
|
|
5781
|
+
callerToolchainBin: toolchain.toolchainBin
|
|
5782
|
+
})
|
|
5783
|
+
);
|
|
5784
|
+
(0, import_node_child_process8.execFileSync)(
|
|
5785
|
+
"bash",
|
|
5786
|
+
[
|
|
5787
|
+
import_node_path12.default.join(repo, "scripts/build/remote.sh"),
|
|
5788
|
+
// a deadline makes a busy pool wait for a slot; without one it refuses
|
|
5789
|
+
// at once and the app reads as missing a module
|
|
5790
|
+
"--timeout",
|
|
5791
|
+
"1800",
|
|
5792
|
+
"--delivery-dir",
|
|
5793
|
+
delivery,
|
|
5794
|
+
"--toolchain",
|
|
5795
|
+
"packages/sootsim-swift/toolchain.json",
|
|
5796
|
+
"--input",
|
|
5797
|
+
request,
|
|
5798
|
+
"--input",
|
|
5799
|
+
artifact.dir,
|
|
5800
|
+
"bun",
|
|
5801
|
+
"scripts/build/swift-standins.ts",
|
|
5802
|
+
"--request",
|
|
5803
|
+
".remote-inputs/request.json",
|
|
5804
|
+
"--artifact",
|
|
5805
|
+
`.remote-inputs/${import_node_path12.default.basename(artifact.dir)}`,
|
|
5806
|
+
"--output",
|
|
5807
|
+
".remote-out/standins.json"
|
|
5808
|
+
],
|
|
5809
|
+
{ cwd: repo, stdio: "inherit" }
|
|
5810
|
+
);
|
|
5811
|
+
const receipt = JSON.parse(
|
|
5812
|
+
import_node_fs12.default.readFileSync(import_node_path12.default.join(delivery, "standins.json"), "utf8")
|
|
5813
|
+
);
|
|
5814
|
+
if (!receipt || typeof receipt !== "object" || !("generation" in receipt) || receipt.generation !== generation || !("result" in receipt))
|
|
5815
|
+
throw new Error("Swift stand-in builder source differs from the caller");
|
|
5816
|
+
const result = receipt.result;
|
|
5817
|
+
if (typeof result === "string") return result;
|
|
5818
|
+
if (!Array.isArray(result) || !result.every(
|
|
5819
|
+
(item) => item && typeof item === "object" && typeof item.module === "string" && typeof item.target === "string" && item.target === binary.target && item.files && typeof item.files === "object" && !Array.isArray(item.files) && Object.values(item.files).every((text3) => typeof text3 === "string")
|
|
5820
|
+
))
|
|
5821
|
+
throw new Error("invalid Swift stand-in builder result");
|
|
5822
|
+
return result;
|
|
5823
|
+
} finally {
|
|
5824
|
+
import_node_fs12.default.rmSync(work, { recursive: true, force: true });
|
|
5825
|
+
}
|
|
5826
|
+
}
|
|
5168
5827
|
function standinGenerationInputs(binaries, toolchain) {
|
|
5169
5828
|
const { moduleRoot, toolchainBin, release } = toolchain;
|
|
5170
5829
|
const parts = [
|
|
@@ -5240,7 +5899,7 @@ function binaryStandins(binary, toolchain, provided) {
|
|
|
5240
5899
|
const work = import_node_fs12.default.mkdtempSync(import_node_path12.default.join(import_node_os7.default.tmpdir(), "peach-standin-"));
|
|
5241
5900
|
let result;
|
|
5242
5901
|
try {
|
|
5243
|
-
result = found.map((surface) => {
|
|
5902
|
+
result = process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && toolchain.moduleRoot === import_node_path12.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(toolchain.moduleRoot) ? sourceBinaryStandins(binary, toolchain, provided) : found.map((surface) => {
|
|
5244
5903
|
const dir = import_node_path12.default.join(work, surface.module);
|
|
5245
5904
|
try {
|
|
5246
5905
|
return surface.kind === "swift" ? swiftStandin(surface, binary, toolchain, dir) : cStandin(surface, binary, toolchain, dir);
|
|
@@ -5250,6 +5909,7 @@ function binaryStandins(binary, toolchain, provided) {
|
|
|
5250
5909
|
);
|
|
5251
5910
|
}
|
|
5252
5911
|
});
|
|
5912
|
+
if (typeof result === "string") return result;
|
|
5253
5913
|
import_node_fs12.default.mkdirSync(import_node_path12.default.dirname(cached2), { recursive: true });
|
|
5254
5914
|
import_node_fs12.default.writeFileSync(cached2, JSON.stringify(result));
|
|
5255
5915
|
built.set(id, result);
|
|
@@ -5270,7 +5930,7 @@ function swiftStandins(binaries, toolchain, provided = /* @__PURE__ */ new Set()
|
|
|
5270
5930
|
}
|
|
5271
5931
|
return { standins, gaps };
|
|
5272
5932
|
}
|
|
5273
|
-
var import_node_child_process8, import_node_crypto6, import_node_fs12, import_node_os7, import_node_path12, TRIPLE, cacheDir3, key, digests, files, OBJC, identChar, built;
|
|
5933
|
+
var import_node_child_process8, import_node_crypto6, import_node_fs12, import_node_os7, import_node_path12, TRIPLE, cacheDir3, key, digests, files, OBJC, identChar, RUST_TARGET, UNSEARCHED, built;
|
|
5274
5934
|
var init_swift_standins = __esm({
|
|
5275
5935
|
"src/swift-standins.ts"() {
|
|
5276
5936
|
"use strict";
|
|
@@ -5289,6 +5949,15 @@ var init_swift_standins = __esm({
|
|
|
5289
5949
|
files = (dir, test) => import_node_fs12.default.existsSync(dir) ? import_node_fs12.default.readdirSync(dir, { recursive: true, encoding: "utf8" }).filter((file) => test(import_node_path12.default.basename(file))).sort() : [];
|
|
5290
5950
|
OBJC = /^\s*(?:@interface|@protocol|@class|@import|#import)\b/m;
|
|
5291
5951
|
identChar = (char) => char !== void 0 && /[\w$]/.test(char);
|
|
5952
|
+
RUST_TARGET = "wasm32-wasip1";
|
|
5953
|
+
UNSEARCHED = /* @__PURE__ */ new Set([
|
|
5954
|
+
"node_modules",
|
|
5955
|
+
"Pods",
|
|
5956
|
+
"target",
|
|
5957
|
+
".build",
|
|
5958
|
+
".git",
|
|
5959
|
+
"DerivedData"
|
|
5960
|
+
]);
|
|
5292
5961
|
built = /* @__PURE__ */ new Map();
|
|
5293
5962
|
}
|
|
5294
5963
|
});
|
|
@@ -5337,7 +6006,11 @@ function isRecord2(value) {
|
|
|
5337
6006
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5338
6007
|
}
|
|
5339
6008
|
function isSwiftNativeModules(value) {
|
|
5340
|
-
return isRecord2(value) && typeof value.packageId === "string" && typeof value.hash === "string" && isRecord2(value.files) && isRecord2(value.modules) &&
|
|
6009
|
+
return isRecord2(value) && typeof value.packageId === "string" && typeof value.hash === "string" && isRecord2(value.files) && isRecord2(value.modules) && isRecord2(value.views) && [
|
|
6010
|
+
...Object.values(value.files),
|
|
6011
|
+
...Object.values(value.modules),
|
|
6012
|
+
...Object.values(value.views)
|
|
6013
|
+
].every(
|
|
5341
6014
|
(names) => Array.isArray(names) && names.every((name2) => typeof name2 === "string")
|
|
5342
6015
|
) && Array.isArray(value.defaultViewFiles) && value.defaultViewFiles.every((file) => typeof file === "string");
|
|
5343
6016
|
}
|
|
@@ -5345,7 +6018,7 @@ function isSwiftCompileOutcome(value) {
|
|
|
5345
6018
|
if (!isRecord2(value)) return false;
|
|
5346
6019
|
switch (value.status) {
|
|
5347
6020
|
case "published":
|
|
5348
|
-
return typeof value.artifactUrl === "string" && typeof value.icuUrl === "string" && typeof value.hash === "string" && /^[a-f0-9]{64}$/.test(value.hash) && (value.imageUrls === void 0 || isRecord2(value.imageUrls) && Object.values(value.imageUrls).every((url) => typeof url === "string")) && (value.native === void 0 || isSwiftNativeModules(value.native));
|
|
6021
|
+
return typeof value.artifactUrl === "string" && typeof value.icuUrl === "string" && typeof value.hash === "string" && /^[a-f0-9]{64}$/.test(value.hash) && (value.imageUrls === void 0 || isRecord2(value.imageUrls) && Object.values(value.imageUrls).every((url) => typeof url === "string")) && (value.metalSources === void 0 || isSwiftMetalLibrarySources(value.metalSources)) && (value.native === void 0 || isSwiftNativeModules(value.native));
|
|
5349
6022
|
case "compiling":
|
|
5350
6023
|
return typeof value.hash === "string" && /^[a-f0-9]{64}$/.test(value.hash);
|
|
5351
6024
|
case "refused":
|
|
@@ -5380,6 +6053,14 @@ async function compileSwiftProject(submit, work, origin, signal) {
|
|
|
5380
6053
|
hash: outcome.hash,
|
|
5381
6054
|
icuUrl: compileAssetUrl(outcome.icuUrl, origin),
|
|
5382
6055
|
...outcome.imageUrls === void 0 ? {} : { imageUrls: resolveImageUrls(outcome.imageUrls, origin) },
|
|
6056
|
+
...outcome.metalSources === void 0 ? {} : {
|
|
6057
|
+
metalSources: Object.fromEntries(
|
|
6058
|
+
Object.entries(outcome.metalSources).map(([file, source]) => [
|
|
6059
|
+
file,
|
|
6060
|
+
{ ...source, url: compileAssetUrl(source.url, origin) }
|
|
6061
|
+
])
|
|
6062
|
+
)
|
|
6063
|
+
},
|
|
5383
6064
|
...outcome.native === void 0 ? {} : { native: outcome.native }
|
|
5384
6065
|
};
|
|
5385
6066
|
case "compiling":
|
|
@@ -5407,20 +6088,24 @@ async function compileSwiftProject(submit, work, origin, signal) {
|
|
|
5407
6088
|
}
|
|
5408
6089
|
}
|
|
5409
6090
|
}
|
|
5410
|
-
var SWIFT_COMPILE_PATH, MAX_SWIFT_COMPILE_FILES, MAX_SWIFT_COMPILE_SOURCE_BYTES, MAX_SWIFT_COMPILE_RESOURCES, MAX_SWIFT_COMPILE_RESOURCE_BYTES, MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES, MAX_SWIFT_COMPILE_IMAGES, MAX_SWIFT_COMPILE_IMAGE_BYTES, MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES, SWIFT_HOST_ABI, POLL_INTERVAL_MS;
|
|
6091
|
+
var SWIFT_COMPILE_PATH, MAX_SWIFT_COMPILE_FILES, MAX_SWIFT_COMPILE_SOURCE_BYTES, MAX_SWIFT_COMPILE_RESOURCES, MAX_SWIFT_COMPILE_RESOURCE_BYTES, MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES, MAX_SWIFT_COMPILE_METAL_FILES, MAX_SWIFT_COMPILE_METAL_BYTES, MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES, MAX_SWIFT_COMPILE_IMAGES, MAX_SWIFT_COMPILE_IMAGE_BYTES, MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES, SWIFT_HOST_ABI, POLL_INTERVAL_MS;
|
|
5411
6092
|
var init_swift_submit = __esm({
|
|
5412
6093
|
"src/swift-submit.ts"() {
|
|
5413
6094
|
"use strict";
|
|
6095
|
+
init_swiftContract();
|
|
5414
6096
|
SWIFT_COMPILE_PATH = "/api/swift-compile";
|
|
5415
6097
|
MAX_SWIFT_COMPILE_FILES = 256;
|
|
5416
6098
|
MAX_SWIFT_COMPILE_SOURCE_BYTES = 2 * 1024 * 1024;
|
|
5417
6099
|
MAX_SWIFT_COMPILE_RESOURCES = 128;
|
|
5418
6100
|
MAX_SWIFT_COMPILE_RESOURCE_BYTES = 2 * 1024 * 1024;
|
|
5419
6101
|
MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES = 8 * 1024 * 1024;
|
|
6102
|
+
MAX_SWIFT_COMPILE_METAL_FILES = 128;
|
|
6103
|
+
MAX_SWIFT_COMPILE_METAL_BYTES = 2 * 1024 * 1024;
|
|
6104
|
+
MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES = 8 * 1024 * 1024;
|
|
5420
6105
|
MAX_SWIFT_COMPILE_IMAGES = 128;
|
|
5421
6106
|
MAX_SWIFT_COMPILE_IMAGE_BYTES = 4 * 1024 * 1024;
|
|
5422
6107
|
MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024;
|
|
5423
|
-
SWIFT_HOST_ABI =
|
|
6108
|
+
SWIFT_HOST_ABI = 41;
|
|
5424
6109
|
POLL_INTERVAL_MS = 1500;
|
|
5425
6110
|
}
|
|
5426
6111
|
});
|
|
@@ -5429,7 +6114,7 @@ var init_swift_submit = __esm({
|
|
|
5429
6114
|
var require_parse = __commonJS({
|
|
5430
6115
|
"../../node_modules/plist/lib/parse.js"(exports2) {
|
|
5431
6116
|
var { DOMParser } = require("@xmldom/xmldom");
|
|
5432
|
-
exports2.parse =
|
|
6117
|
+
exports2.parse = parse2;
|
|
5433
6118
|
var TEXT_NODE = 3;
|
|
5434
6119
|
var CDATA_NODE = 4;
|
|
5435
6120
|
var COMMENT_NODE = 8;
|
|
@@ -5448,7 +6133,7 @@ var require_parse = __commonJS({
|
|
|
5448
6133
|
throw new Error(message);
|
|
5449
6134
|
}
|
|
5450
6135
|
}
|
|
5451
|
-
function
|
|
6136
|
+
function parse2(xml) {
|
|
5452
6137
|
var doc = new DOMParser().parseFromString(xml, "text/xml");
|
|
5453
6138
|
invariant(
|
|
5454
6139
|
doc.documentElement.nodeName === "plist",
|
|
@@ -5710,7 +6395,7 @@ var require_parse2 = __commonJS({
|
|
|
5710
6395
|
var token;
|
|
5711
6396
|
var key2;
|
|
5712
6397
|
var root;
|
|
5713
|
-
module2.exports = function
|
|
6398
|
+
module2.exports = function parse2(text3, reviver) {
|
|
5714
6399
|
source = String(text3);
|
|
5715
6400
|
parseState = "start";
|
|
5716
6401
|
stack = [];
|
|
@@ -5893,15 +6578,15 @@ var require_parse2 = __commonJS({
|
|
|
5893
6578
|
return newToken("punctuator", read());
|
|
5894
6579
|
case "n":
|
|
5895
6580
|
read();
|
|
5896
|
-
|
|
6581
|
+
literal2("ull");
|
|
5897
6582
|
return newToken("null", null);
|
|
5898
6583
|
case "t":
|
|
5899
6584
|
read();
|
|
5900
|
-
|
|
6585
|
+
literal2("rue");
|
|
5901
6586
|
return newToken("boolean", true);
|
|
5902
6587
|
case "f":
|
|
5903
6588
|
read();
|
|
5904
|
-
|
|
6589
|
+
literal2("alse");
|
|
5905
6590
|
return newToken("boolean", false);
|
|
5906
6591
|
case "-":
|
|
5907
6592
|
case "+":
|
|
@@ -5932,11 +6617,11 @@ var require_parse2 = __commonJS({
|
|
|
5932
6617
|
return;
|
|
5933
6618
|
case "I":
|
|
5934
6619
|
read();
|
|
5935
|
-
|
|
6620
|
+
literal2("nfinity");
|
|
5936
6621
|
return newToken("numeric", Infinity);
|
|
5937
6622
|
case "N":
|
|
5938
6623
|
read();
|
|
5939
|
-
|
|
6624
|
+
literal2("aN");
|
|
5940
6625
|
return newToken("numeric", NaN);
|
|
5941
6626
|
case '"':
|
|
5942
6627
|
case "'":
|
|
@@ -6030,11 +6715,11 @@ var require_parse2 = __commonJS({
|
|
|
6030
6715
|
return;
|
|
6031
6716
|
case "I":
|
|
6032
6717
|
read();
|
|
6033
|
-
|
|
6718
|
+
literal2("nfinity");
|
|
6034
6719
|
return newToken("numeric", sign * Infinity);
|
|
6035
6720
|
case "N":
|
|
6036
6721
|
read();
|
|
6037
|
-
|
|
6722
|
+
literal2("aN");
|
|
6038
6723
|
return newToken("numeric", NaN);
|
|
6039
6724
|
}
|
|
6040
6725
|
throw invalidChar(read());
|
|
@@ -6267,7 +6952,7 @@ var require_parse2 = __commonJS({
|
|
|
6267
6952
|
column
|
|
6268
6953
|
};
|
|
6269
6954
|
}
|
|
6270
|
-
function
|
|
6955
|
+
function literal2(s) {
|
|
6271
6956
|
for (const c2 of s) {
|
|
6272
6957
|
const p = peek();
|
|
6273
6958
|
if (p !== c2) {
|
|
@@ -6766,10 +7451,10 @@ var require_stringify = __commonJS({
|
|
|
6766
7451
|
// ../../node_modules/json5/lib/index.js
|
|
6767
7452
|
var require_lib = __commonJS({
|
|
6768
7453
|
"../../node_modules/json5/lib/index.js"(exports2, module2) {
|
|
6769
|
-
var
|
|
7454
|
+
var parse2 = require_parse2();
|
|
6770
7455
|
var stringify = require_stringify();
|
|
6771
7456
|
var JSON52 = {
|
|
6772
|
-
parse,
|
|
7457
|
+
parse: parse2,
|
|
6773
7458
|
stringify
|
|
6774
7459
|
};
|
|
6775
7460
|
module2.exports = JSON52;
|
|
@@ -7115,7 +7800,7 @@ var init_xcode_json_project = __esm({
|
|
|
7115
7800
|
}
|
|
7116
7801
|
});
|
|
7117
7802
|
|
|
7118
|
-
// src/
|
|
7803
|
+
// src/openstep-plist.ts
|
|
7119
7804
|
function parseOpenStepPlist(text3) {
|
|
7120
7805
|
let i = 0;
|
|
7121
7806
|
const fail = (message) => {
|
|
@@ -7173,6 +7858,7 @@ function parseOpenStepPlist(text3) {
|
|
|
7173
7858
|
if (typeof key2 !== "string") fail("dictionary key is not a string");
|
|
7174
7859
|
skip();
|
|
7175
7860
|
if (text3[i++] !== "=") fail("expected =");
|
|
7861
|
+
if (Object.hasOwn(dict, key2)) fail(`duplicate key ${key2}`);
|
|
7176
7862
|
dict[key2] = value();
|
|
7177
7863
|
skip();
|
|
7178
7864
|
if (text3[i++] !== ";") fail("expected ;");
|
|
@@ -7205,6 +7891,17 @@ function parseOpenStepPlist(text3) {
|
|
|
7205
7891
|
if (i !== text3.length) fail("trailing content");
|
|
7206
7892
|
return root;
|
|
7207
7893
|
}
|
|
7894
|
+
var isDict, str, list;
|
|
7895
|
+
var init_openstep_plist = __esm({
|
|
7896
|
+
"src/openstep-plist.ts"() {
|
|
7897
|
+
"use strict";
|
|
7898
|
+
isDict = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7899
|
+
str = (value) => typeof value === "string" ? value : void 0;
|
|
7900
|
+
list = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
7901
|
+
}
|
|
7902
|
+
});
|
|
7903
|
+
|
|
7904
|
+
// src/xcode-project.ts
|
|
7208
7905
|
function walkFiles(dir) {
|
|
7209
7906
|
if (!import_node_fs13.default.existsSync(dir)) return [];
|
|
7210
7907
|
const out = [];
|
|
@@ -7216,9 +7913,9 @@ function walkFiles(dir) {
|
|
|
7216
7913
|
}
|
|
7217
7914
|
return out;
|
|
7218
7915
|
}
|
|
7219
|
-
function readXcconfig(file,
|
|
7220
|
-
if (
|
|
7221
|
-
|
|
7916
|
+
function readXcconfig(file, read) {
|
|
7917
|
+
if (read.includes(file) || !import_node_fs13.default.existsSync(file)) return {};
|
|
7918
|
+
read.push(file);
|
|
7222
7919
|
const settings = {};
|
|
7223
7920
|
for (const raw2 of import_node_fs13.default.readFileSync(file, "utf8").split("\n")) {
|
|
7224
7921
|
const line = raw2.replace(/\/\/.*$/, "").trim();
|
|
@@ -7226,7 +7923,7 @@ function readXcconfig(file, seen = /* @__PURE__ */ new Set()) {
|
|
|
7226
7923
|
if (include) {
|
|
7227
7924
|
Object.assign(
|
|
7228
7925
|
settings,
|
|
7229
|
-
readXcconfig(import_node_path14.default.resolve(import_node_path14.default.dirname(file), include[1]),
|
|
7926
|
+
readXcconfig(import_node_path14.default.resolve(import_node_path14.default.dirname(file), include[1]), read)
|
|
7230
7927
|
);
|
|
7231
7928
|
continue;
|
|
7232
7929
|
}
|
|
@@ -7307,7 +8004,7 @@ function workspaceReferences(workspace) {
|
|
|
7307
8004
|
function enclosingXcodeWorkspace(xcodeproj) {
|
|
7308
8005
|
const project = import_node_fs13.default.realpathSync(xcodeproj);
|
|
7309
8006
|
for (let dir = import_node_path14.default.dirname(project); ; dir = import_node_path14.default.dirname(dir)) {
|
|
7310
|
-
for (const name2 of import_node_fs13.default.readdirSync(dir)) {
|
|
8007
|
+
for (const name2 of import_node_fs13.default.readdirSync(dir).sort()) {
|
|
7311
8008
|
if (!name2.endsWith(".xcworkspace")) continue;
|
|
7312
8009
|
const workspace = import_node_path14.default.join(dir, name2);
|
|
7313
8010
|
if (!import_node_fs13.default.existsSync(import_node_path14.default.join(workspace, "contents.xcworkspacedata"))) continue;
|
|
@@ -7388,17 +8085,30 @@ function loadProject(xcodeproj) {
|
|
|
7388
8085
|
loaded.set(projectFile, { mtimeMs, project: result });
|
|
7389
8086
|
return result;
|
|
7390
8087
|
}
|
|
7391
|
-
function
|
|
8088
|
+
function defaultConfiguration(project) {
|
|
8089
|
+
const configList = project.object(str(project.project.buildConfigurationList));
|
|
8090
|
+
const names = list(configList?.buildConfigurations).flatMap(
|
|
8091
|
+
(id) => str(project.object(id)?.name) ?? []
|
|
8092
|
+
);
|
|
8093
|
+
return names.includes("Debug") ? "Debug" : str(configList?.defaultConfigurationName) ?? names[0] ?? "Debug";
|
|
8094
|
+
}
|
|
8095
|
+
function targetSettings(ref, configuration, builtins) {
|
|
7392
8096
|
const { project, target } = ref;
|
|
8097
|
+
const xcconfigs = [];
|
|
7393
8098
|
const level = (listId) => {
|
|
7394
|
-
const
|
|
7395
|
-
const
|
|
8099
|
+
const configList = project.object(listId);
|
|
8100
|
+
const configs = list(configList?.buildConfigurations).map(project.object);
|
|
8101
|
+
const config = configs.find((entry) => entry?.name === configuration) ?? configs.find((entry) => entry?.name === str(configList?.defaultConfigurationName));
|
|
7396
8102
|
if (!config) return [];
|
|
7397
|
-
const name2 = str(config.name) ??
|
|
8103
|
+
const name2 = str(config.name) ?? configuration;
|
|
7398
8104
|
const base = str(config.baseConfigurationReference);
|
|
7399
8105
|
const own = isDict(config.buildSettings) ? config.buildSettings : {};
|
|
8106
|
+
const baseFile = base ? project.resolvePath(base) : null;
|
|
8107
|
+
const read = [];
|
|
8108
|
+
const fromFile = baseFile ? readXcconfig(baseFile, read) : {};
|
|
8109
|
+
xcconfigs.push(...read);
|
|
7400
8110
|
return [
|
|
7401
|
-
applyConditions(
|
|
8111
|
+
applyConditions(fromFile, name2),
|
|
7402
8112
|
applyConditions(
|
|
7403
8113
|
Object.fromEntries(
|
|
7404
8114
|
Object.entries(own).flatMap(
|
|
@@ -7410,7 +8120,7 @@ function targetSettings(ref, builtins) {
|
|
|
7410
8120
|
];
|
|
7411
8121
|
};
|
|
7412
8122
|
const levels = [
|
|
7413
|
-
builtins,
|
|
8123
|
+
{ ...builtins, CONFIGURATION: configuration },
|
|
7414
8124
|
...level(str(project.project.buildConfigurationList)),
|
|
7415
8125
|
...level(str(target.buildConfigurationList))
|
|
7416
8126
|
];
|
|
@@ -7449,9 +8159,30 @@ function targetSettings(ref, builtins) {
|
|
|
7449
8159
|
};
|
|
7450
8160
|
return {
|
|
7451
8161
|
get: (key2) => valueAt(key2, levels.length - 1),
|
|
7452
|
-
keys: new Set(levels.flatMap((values) => Object.keys(values)))
|
|
8162
|
+
keys: new Set(levels.flatMap((values) => Object.keys(values))),
|
|
8163
|
+
xcconfigs
|
|
7453
8164
|
};
|
|
7454
8165
|
}
|
|
8166
|
+
function settingList(value) {
|
|
8167
|
+
const items2 = [];
|
|
8168
|
+
for (const [, quoted, plain] of value.matchAll(
|
|
8169
|
+
/"((?:\\.|[^"\\])*)"|((?:\\.|[^\s"])+)/g
|
|
8170
|
+
))
|
|
8171
|
+
items2.push((quoted ?? plain).replace(/\\(.)/g, "$1"));
|
|
8172
|
+
return items2;
|
|
8173
|
+
}
|
|
8174
|
+
function compilationConditions(settings) {
|
|
8175
|
+
const flags = settingList(settings("OTHER_SWIFT_FLAGS"));
|
|
8176
|
+
const defined = flags.flatMap(
|
|
8177
|
+
(flag, index) => flag === "-D" ? flags[index + 1] ?? [] : flag.startsWith("-D") ? flag.slice(2) : []
|
|
8178
|
+
);
|
|
8179
|
+
return [
|
|
8180
|
+
.../* @__PURE__ */ new Set([
|
|
8181
|
+
...settingList(settings("SWIFT_ACTIVE_COMPILATION_CONDITIONS")),
|
|
8182
|
+
...defined
|
|
8183
|
+
])
|
|
8184
|
+
];
|
|
8185
|
+
}
|
|
7455
8186
|
function expand(value, lookup) {
|
|
7456
8187
|
return value.replace(
|
|
7457
8188
|
/\$(?:\(([A-Za-z_][A-Za-z0-9_]*)((?::[^)]*)?)\)|\{([A-Za-z_][A-Za-z0-9_]*)((?::[^}]*)?)\}|([A-Za-z_][A-Za-z0-9_]*))/g,
|
|
@@ -7462,8 +8193,9 @@ function expand(value, lookup) {
|
|
|
7462
8193
|
}
|
|
7463
8194
|
);
|
|
7464
8195
|
}
|
|
7465
|
-
function targetMembers(ref) {
|
|
8196
|
+
function targetMembers(ref, settings, options = {}) {
|
|
7466
8197
|
const { project, target, id: targetId } = ref;
|
|
8198
|
+
const targetName = str(target.name) ?? targetId;
|
|
7467
8199
|
const sources = /* @__PURE__ */ new Set();
|
|
7468
8200
|
const allSources = /* @__PURE__ */ new Set();
|
|
7469
8201
|
const resources = /* @__PURE__ */ new Set();
|
|
@@ -7484,20 +8216,60 @@ function targetMembers(ref) {
|
|
|
7484
8216
|
const resolved = project.resolvePath(refId);
|
|
7485
8217
|
return resolved ? [resolved] : [];
|
|
7486
8218
|
};
|
|
8219
|
+
const scriptForOutput = /* @__PURE__ */ new Map();
|
|
8220
|
+
const noteScriptOutput = (raw2, script) => {
|
|
8221
|
+
const expanded = expand(raw2, settings);
|
|
8222
|
+
if (!expanded.endsWith(".swift")) return;
|
|
8223
|
+
const absolute = import_node_path14.default.isAbsolute(expanded) ? import_node_path14.default.normalize(expanded) : import_node_path14.default.resolve(project.projectDir, expanded);
|
|
8224
|
+
if (!scriptForOutput.has(absolute)) scriptForOutput.set(absolute, script);
|
|
8225
|
+
};
|
|
7487
8226
|
for (const phaseId of list(target.buildPhases)) {
|
|
7488
8227
|
const phase = project.object(phaseId);
|
|
7489
|
-
if (phase?.isa !== "
|
|
7490
|
-
|
|
7491
|
-
for (const
|
|
8228
|
+
if (phase?.isa !== "PBXShellScriptBuildPhase") continue;
|
|
8229
|
+
const script = str(phase.name) ?? phaseId;
|
|
8230
|
+
for (const raw2 of list(phase.outputPaths)) noteScriptOutput(raw2, script);
|
|
8231
|
+
for (const listPath of list(phase.outputFileListPaths)) {
|
|
8232
|
+
const expandedList = expand(listPath, settings);
|
|
8233
|
+
const absoluteList = import_node_path14.default.isAbsolute(expandedList) ? expandedList : import_node_path14.default.resolve(project.projectDir, expandedList);
|
|
8234
|
+
if (!import_node_fs13.default.existsSync(absoluteList)) continue;
|
|
8235
|
+
for (const line of import_node_fs13.default.readFileSync(absoluteList, "utf8").split("\n")) {
|
|
8236
|
+
const trimmed = line.trim();
|
|
8237
|
+
if (trimmed === "" || trimmed.startsWith("#")) continue;
|
|
8238
|
+
noteScriptOutput(trimmed, script);
|
|
8239
|
+
}
|
|
8240
|
+
}
|
|
8241
|
+
}
|
|
8242
|
+
for (const phaseId of list(target.buildPhases)) {
|
|
8243
|
+
const phase = project.object(phaseId);
|
|
8244
|
+
if (phase?.isa !== "PBXSourcesBuildPhase" && phase?.isa !== "PBXResourcesBuildPhase")
|
|
8245
|
+
continue;
|
|
8246
|
+
for (const buildFileId of list(phase.files)) {
|
|
7492
8247
|
for (const file of fileRefPaths(str(project.object(buildFileId)?.fileRef) ?? "")) {
|
|
7493
8248
|
if (phase.isa === "PBXSourcesBuildPhase") {
|
|
7494
|
-
if (!import_node_fs13.default.existsSync(file))
|
|
8249
|
+
if (!import_node_fs13.default.existsSync(file)) {
|
|
8250
|
+
if (options.requireSources === false) continue;
|
|
8251
|
+
const script = scriptForOutput.get(import_node_path14.default.normalize(file));
|
|
8252
|
+
throw new Error(
|
|
8253
|
+
script ? `${targetName}: missing generated source ${file} (Run Script "${script}" declares it in outputPaths; run the script or check in its output)` : `${targetName}: missing source ${file}`
|
|
8254
|
+
);
|
|
8255
|
+
}
|
|
7495
8256
|
allSources.add(file);
|
|
7496
8257
|
if (file.endsWith(".swift")) sources.add(file);
|
|
7497
8258
|
} else if (phase.isa === "PBXResourcesBuildPhase") addResource(file);
|
|
7498
8259
|
}
|
|
7499
8260
|
}
|
|
7500
8261
|
}
|
|
8262
|
+
for (const [file, script] of scriptForOutput) {
|
|
8263
|
+
if (sources.has(file) || allSources.has(file)) continue;
|
|
8264
|
+
if (!import_node_fs13.default.existsSync(file)) {
|
|
8265
|
+
if (options.requireSources === false) continue;
|
|
8266
|
+
throw new Error(
|
|
8267
|
+
`${targetName}: missing generated source ${file} (Run Script "${script}" declares it in outputPaths; run the script or check in its output)`
|
|
8268
|
+
);
|
|
8269
|
+
}
|
|
8270
|
+
allSources.add(file);
|
|
8271
|
+
sources.add(file);
|
|
8272
|
+
}
|
|
7501
8273
|
const addSynchronized = (folder, relative) => {
|
|
7502
8274
|
const file = import_node_path14.default.join(folder, relative);
|
|
7503
8275
|
if (NEVER_MEMBER.test(relative)) return;
|
|
@@ -7596,7 +8368,7 @@ function nativeTargets(project) {
|
|
|
7596
8368
|
}
|
|
7597
8369
|
return refs;
|
|
7598
8370
|
}
|
|
7599
|
-
function readXcodeAppTarget(input, targetName) {
|
|
8371
|
+
function readXcodeAppTarget(input, targetName, configurationName, options = {}) {
|
|
7600
8372
|
const xcodeprojOrWorkspace = import_node_fs13.default.realpathSync(input);
|
|
7601
8373
|
const workspace = xcodeprojOrWorkspace.endsWith(".xcworkspace") ? xcodeprojOrWorkspace : null;
|
|
7602
8374
|
const { listed, projects: projects2, projectAt } = workspaceProjects(xcodeprojOrWorkspace);
|
|
@@ -7611,6 +8383,7 @@ function readXcodeAppTarget(input, targetName) {
|
|
|
7611
8383
|
);
|
|
7612
8384
|
}
|
|
7613
8385
|
const app = named[0];
|
|
8386
|
+
const configuration = configurationName ?? defaultConfiguration(app.project);
|
|
7614
8387
|
const byProduct = /* @__PURE__ */ new Map();
|
|
7615
8388
|
for (const ref of allTargets) {
|
|
7616
8389
|
const product = ref.project.object(str(ref.target.productReference));
|
|
@@ -7661,9 +8434,14 @@ function readXcodeAppTarget(input, targetName) {
|
|
|
7661
8434
|
order.push(ref);
|
|
7662
8435
|
};
|
|
7663
8436
|
visit(app);
|
|
8437
|
+
const xcconfigs = /* @__PURE__ */ new Set();
|
|
7664
8438
|
const moduleTarget = (ref) => {
|
|
7665
8439
|
const name2 = str(ref.target.name) ?? ref.id;
|
|
7666
|
-
const {
|
|
8440
|
+
const {
|
|
8441
|
+
get: settings2,
|
|
8442
|
+
keys,
|
|
8443
|
+
xcconfigs: read
|
|
8444
|
+
} = targetSettings(ref, configuration, {
|
|
7667
8445
|
TARGET_NAME: name2,
|
|
7668
8446
|
PROJECT_NAME: import_node_path14.default.basename(ref.project.xcodeproj, ".xcodeproj"),
|
|
7669
8447
|
SRCROOT: ref.project.projectDir,
|
|
@@ -7671,6 +8449,7 @@ function readXcodeAppTarget(input, targetName) {
|
|
|
7671
8449
|
PROJECT_DIR: ref.project.projectDir,
|
|
7672
8450
|
DEVELOPMENT_LANGUAGE: str(ref.project.project.developmentRegion) ?? "en"
|
|
7673
8451
|
});
|
|
8452
|
+
for (const file of read) xcconfigs.add(file);
|
|
7674
8453
|
const swiftVersion = Number.parseFloat(settings2("SWIFT_VERSION") || "5");
|
|
7675
8454
|
return {
|
|
7676
8455
|
settings: settings2,
|
|
@@ -7678,9 +8457,10 @@ function readXcodeAppTarget(input, targetName) {
|
|
|
7678
8457
|
module: {
|
|
7679
8458
|
name: name2,
|
|
7680
8459
|
moduleName: applyOperator(settings2("PRODUCT_MODULE_NAME"), "c99extidentifier"),
|
|
7681
|
-
...targetMembers(ref),
|
|
8460
|
+
...targetMembers(ref, settings2, options),
|
|
7682
8461
|
languageMode: swiftVersion >= 6 ? 6 : 5,
|
|
7683
|
-
mainActorIsolation: settings2("SWIFT_DEFAULT_ACTOR_ISOLATION") === "MainActor"
|
|
8462
|
+
mainActorIsolation: settings2("SWIFT_DEFAULT_ACTOR_ISOLATION") === "MainActor",
|
|
8463
|
+
defines: compilationConditions(settings2)
|
|
7684
8464
|
}
|
|
7685
8465
|
};
|
|
7686
8466
|
};
|
|
@@ -7786,7 +8566,9 @@ function readXcodeAppTarget(input, targetName) {
|
|
|
7786
8566
|
)
|
|
7787
8567
|
].map((dir) => import_node_fs13.default.realpathSync(dir))
|
|
7788
8568
|
),
|
|
7789
|
-
projectFiles: [
|
|
8569
|
+
projectFiles: [
|
|
8570
|
+
.../* @__PURE__ */ new Set([...used.map((project) => project.projectFile), ...xcconfigs])
|
|
8571
|
+
].sort(),
|
|
7790
8572
|
appIconName: settings("ASSETCATALOG_COMPILER_APPICON_NAME"),
|
|
7791
8573
|
infoPlist: import_plist.default.build(info),
|
|
7792
8574
|
infoPlistFile,
|
|
@@ -7797,10 +8579,12 @@ function readXcodeAppTarget(input, targetName) {
|
|
|
7797
8579
|
].sort(),
|
|
7798
8580
|
binaryFrameworks: [...binaryFrameworks].map(([name2, file]) => ({ name: name2, path: file })).sort((left, right) => left.name.localeCompare(right.name)),
|
|
7799
8581
|
packageResolved: import_node_fs13.default.existsSync(resolvedFile) ? resolvedFile : null,
|
|
7800
|
-
appTargets: appTargetNames
|
|
8582
|
+
appTargets: appTargetNames,
|
|
8583
|
+
configuration,
|
|
8584
|
+
settings
|
|
7801
8585
|
};
|
|
7802
8586
|
}
|
|
7803
|
-
var import_node_fs13, import_node_path14, import_plist,
|
|
8587
|
+
var import_node_fs13, import_node_path14, import_plist, APPLICATION, MODULE_PRODUCTS, NEVER_MEMBER, BUNDLE_DIR, CONDITIONS, isDirectory, loaded, targetRefs;
|
|
7804
8588
|
var init_xcode_project = __esm({
|
|
7805
8589
|
"src/xcode-project.ts"() {
|
|
7806
8590
|
"use strict";
|
|
@@ -7808,9 +8592,8 @@ var init_xcode_project = __esm({
|
|
|
7808
8592
|
import_node_path14 = __toESM(require("node:path"), 1);
|
|
7809
8593
|
import_plist = __toESM(require_plist(), 1);
|
|
7810
8594
|
init_xcode_json_project();
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
list = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
8595
|
+
init_openstep_plist();
|
|
8596
|
+
init_openstep_plist();
|
|
7814
8597
|
APPLICATION = "com.apple.product-type.application";
|
|
7815
8598
|
MODULE_PRODUCTS = /* @__PURE__ */ new Set([
|
|
7816
8599
|
"com.apple.product-type.framework",
|
|
@@ -7947,7 +8730,7 @@ function swiftPackages(entry, app) {
|
|
|
7947
8730
|
cached2.standinKey = generation;
|
|
7948
8731
|
}
|
|
7949
8732
|
}
|
|
7950
|
-
return cached2;
|
|
8733
|
+
return { ...cached2, binaries: reached };
|
|
7951
8734
|
}
|
|
7952
8735
|
function xcodeInputKey(layout, file, relative) {
|
|
7953
8736
|
const owner = layout.targetDirs.get(file);
|
|
@@ -7957,14 +8740,37 @@ function xcodeInputKey(layout, file, relative) {
|
|
|
7957
8740
|
function xcodeLayout(root) {
|
|
7958
8741
|
const registered = xcodeProjects.get(root);
|
|
7959
8742
|
if (!registered) return null;
|
|
7960
|
-
const app = readXcodeAppTarget(
|
|
7961
|
-
|
|
8743
|
+
const app = readXcodeAppTarget(
|
|
8744
|
+
registered.xcodeproj,
|
|
8745
|
+
registered.target,
|
|
8746
|
+
registered.configuration
|
|
8747
|
+
);
|
|
8748
|
+
const appSources = app.allSources.filter(
|
|
8749
|
+
(file) => file.endsWith(".swift") || file.endsWith(".metal")
|
|
8750
|
+
);
|
|
8751
|
+
const files2 = /* @__PURE__ */ new Set([...app.projectFiles, ...appSources, ...app.resources]);
|
|
7962
8752
|
if (app.infoPlistFile) files2.add(app.infoPlistFile);
|
|
7963
|
-
const targetDirs = new Map(
|
|
8753
|
+
const targetDirs = new Map(
|
|
8754
|
+
[...appSources, ...app.resources].map((file) => [file, XCODE_APP_DIR])
|
|
8755
|
+
);
|
|
8756
|
+
const resourceBundles = [
|
|
8757
|
+
{ target: app.moduleName, sourcePath: XCODE_APP_DIR, path: "." }
|
|
8758
|
+
];
|
|
7964
8759
|
const targets = [];
|
|
7965
8760
|
for (const framework of app.frameworks) {
|
|
7966
8761
|
const dir = import_node_path15.default.posix.join(XCODE_FRAMEWORKS_DIR, framework.moduleName);
|
|
7967
|
-
|
|
8762
|
+
resourceBundles.push({
|
|
8763
|
+
target: framework.moduleName,
|
|
8764
|
+
sourcePath: dir,
|
|
8765
|
+
path: `Frameworks/${framework.moduleName}.framework`
|
|
8766
|
+
});
|
|
8767
|
+
for (const file of framework.allSources) {
|
|
8768
|
+
if (!file.endsWith(".swift") && !file.endsWith(".metal")) continue;
|
|
8769
|
+
if (targetDirs.has(file)) continue;
|
|
8770
|
+
targetDirs.set(file, dir);
|
|
8771
|
+
files2.add(file);
|
|
8772
|
+
}
|
|
8773
|
+
for (const file of framework.resources) {
|
|
7968
8774
|
if (targetDirs.has(file)) continue;
|
|
7969
8775
|
targetDirs.set(file, dir);
|
|
7970
8776
|
files2.add(file);
|
|
@@ -7976,10 +8782,11 @@ function xcodeLayout(root) {
|
|
|
7976
8782
|
resources: false,
|
|
7977
8783
|
exclude: [],
|
|
7978
8784
|
languageMode: framework.languageMode,
|
|
7979
|
-
mainActorIsolation: framework.mainActorIsolation
|
|
8785
|
+
mainActorIsolation: framework.mainActorIsolation,
|
|
8786
|
+
defines: framework.defines
|
|
7980
8787
|
});
|
|
7981
8788
|
}
|
|
7982
|
-
const { packages, standins, projectGaps } = swiftPackages(registered, app);
|
|
8789
|
+
const { packages, standins, projectGaps, binaries } = swiftPackages(registered, app);
|
|
7983
8790
|
for (const standin of standins)
|
|
7984
8791
|
targets.push({
|
|
7985
8792
|
name: standin.module,
|
|
@@ -7990,6 +8797,7 @@ function xcodeLayout(root) {
|
|
|
7990
8797
|
languageMode: 5,
|
|
7991
8798
|
mainActorIsolation: false
|
|
7992
8799
|
});
|
|
8800
|
+
const packageConfiguration = app.configuration === "Debug" ? "debug" : "release";
|
|
7993
8801
|
for (const target of packages.targets) {
|
|
7994
8802
|
const relative = import_node_path15.default.relative(
|
|
7995
8803
|
target.remote ? import_node_path15.default.join(root, REMOTE_CHECKOUTS) : root,
|
|
@@ -8001,8 +8809,21 @@ function xcodeLayout(root) {
|
|
|
8001
8809
|
targets.push({
|
|
8002
8810
|
...target,
|
|
8003
8811
|
path: target.remote ? import_node_path15.default.posix.join(XCODE_PACKAGES_DIR, posix) : posix,
|
|
8004
|
-
exclude: []
|
|
8812
|
+
exclude: [],
|
|
8813
|
+
defines: [
|
|
8814
|
+
...packageConfiguration === "debug" ? ["DEBUG"] : [],
|
|
8815
|
+
...target.packageDefines.filter(
|
|
8816
|
+
(define) => define.configuration === null || define.configuration === packageConfiguration
|
|
8817
|
+
).map((define) => define.name)
|
|
8818
|
+
]
|
|
8005
8819
|
});
|
|
8820
|
+
if (target.resources) {
|
|
8821
|
+
resourceBundles.push({
|
|
8822
|
+
target: target.name,
|
|
8823
|
+
sourcePath: target.remote ? import_node_path15.default.posix.join(XCODE_PACKAGES_DIR, posix) : posix,
|
|
8824
|
+
path: `${swiftPackageManifest(target.packageDir).name}_${target.name}.bundle`
|
|
8825
|
+
});
|
|
8826
|
+
}
|
|
8006
8827
|
if (!target.remote) files2.add(import_node_path15.default.join(target.packageDir, "Package.swift"));
|
|
8007
8828
|
for (const file of target.files) files2.add(file);
|
|
8008
8829
|
}
|
|
@@ -8014,20 +8835,26 @@ function xcodeLayout(root) {
|
|
|
8014
8835
|
targets,
|
|
8015
8836
|
packages,
|
|
8016
8837
|
standins,
|
|
8838
|
+
binaries,
|
|
8017
8839
|
projectGaps,
|
|
8018
8840
|
targetDirs,
|
|
8841
|
+
resourceBundles,
|
|
8019
8842
|
files: [...files2].sort()
|
|
8020
8843
|
};
|
|
8021
8844
|
}
|
|
8022
8845
|
function xcodeManifest(layout) {
|
|
8023
|
-
const settings = (
|
|
8846
|
+
const settings = (target) => `swiftSettings: [${[
|
|
8847
|
+
`.swiftLanguageMode(.v${target.languageMode})`,
|
|
8848
|
+
...target.mainActorIsolation ? [".defaultIsolation(MainActor.self)"] : [],
|
|
8849
|
+
...(target.defines ?? []).map((name2) => `.define(${JSON.stringify(name2)})`)
|
|
8850
|
+
].join(", ")}]`;
|
|
8024
8851
|
return [
|
|
8025
8852
|
"// swift-tools-version: 6.2",
|
|
8026
8853
|
"import PackageDescription",
|
|
8027
8854
|
'let package = Package(name: "app", targets: [',
|
|
8028
|
-
` .executableTarget(name: "${layout.app.moduleName}", path: "${XCODE_APP_DIR}", ${settings(layout.app
|
|
8855
|
+
` .executableTarget(name: "${layout.app.moduleName}", path: "${XCODE_APP_DIR}", ${settings(layout.app)}),`,
|
|
8029
8856
|
...layout.targets.map(
|
|
8030
|
-
(target) => ` .target(name: "${target.name}", path: "${target.path}", ${target.exclude.length > 0 ? `exclude: ${JSON.stringify(target.exclude)}, ` : ""}${target.resources ? "resources: [], " : ""}${settings(target
|
|
8857
|
+
(target) => ` .target(name: "${target.name}", path: "${target.path}", ${target.exclude.length > 0 ? `exclude: ${JSON.stringify(target.exclude)}, ` : ""}${target.resources ? "resources: [], " : ""}${settings(target)}),`
|
|
8031
8858
|
),
|
|
8032
8859
|
"])",
|
|
8033
8860
|
""
|
|
@@ -8068,10 +8895,10 @@ function sourceFiles(root) {
|
|
|
8068
8895
|
}
|
|
8069
8896
|
function resourceCandidateFiles(root) {
|
|
8070
8897
|
return packageFiles(root).filter(
|
|
8071
|
-
(file) => !file.endsWith(".swift") && !["project.pbxproj", "project.xcproj"].includes(import_node_path15.default.basename(file))
|
|
8898
|
+
(file) => !file.endsWith(".swift") && !file.endsWith(".xcconfig") && !["project.pbxproj", "project.xcproj"].includes(import_node_path15.default.basename(file))
|
|
8072
8899
|
);
|
|
8073
8900
|
}
|
|
8074
|
-
function buildSwiftResourceTable(project, baseUrl) {
|
|
8901
|
+
function buildSwiftResourceTable(project, baseUrl, inputs) {
|
|
8075
8902
|
const limits = inputLimits(Boolean(project.hosted));
|
|
8076
8903
|
const absolute = resourceCandidateFiles(project.packagePath);
|
|
8077
8904
|
const relative = absolute.map(
|
|
@@ -8086,15 +8913,77 @@ function buildSwiftResourceTable(project, baseUrl) {
|
|
|
8086
8913
|
"utf8"
|
|
8087
8914
|
);
|
|
8088
8915
|
};
|
|
8089
|
-
const
|
|
8090
|
-
const
|
|
8091
|
-
const
|
|
8092
|
-
|
|
8916
|
+
const layout = xcodeLayout(project.packagePath);
|
|
8917
|
+
const bundles = layout?.resourceBundles ?? swiftResourceBundles(inputs, relative);
|
|
8918
|
+
const catalogFiles = relative.filter((file) => {
|
|
8919
|
+
const disk = byRelative.get(file);
|
|
8920
|
+
return !disk || !layout?.targetDirs.get(disk)?.startsWith(`${XCODE_FRAMEWORKS_DIR}/`);
|
|
8921
|
+
});
|
|
8922
|
+
const found = enumerateBundleImages(relative, readContents, (file) => {
|
|
8923
|
+
const disk = byRelative.get(file);
|
|
8924
|
+
if (!disk) throw new Error(`image source ${file} has no input file`);
|
|
8925
|
+
const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
|
|
8926
|
+
return swiftResourceBundleForFile(bundles, key2)?.path ?? ".";
|
|
8927
|
+
});
|
|
8928
|
+
const colors = enumerateBundleColors(catalogFiles, readContents);
|
|
8929
|
+
const symbols = enumerateBundleSymbols(catalogFiles, readContents, (file) => {
|
|
8930
|
+
const disk = byRelative.get(file);
|
|
8931
|
+
if (!disk) throw new Error(`symbol source ${file} has no input file`);
|
|
8932
|
+
const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
|
|
8933
|
+
return swiftResourceBundleForFile(bundles, key2)?.path ?? ".";
|
|
8934
|
+
});
|
|
8935
|
+
const table = /* @__PURE__ */ Object.create(null);
|
|
8093
8936
|
const images = {};
|
|
8937
|
+
const metalSources = {};
|
|
8938
|
+
const metalUploads = {};
|
|
8094
8939
|
const watched = [];
|
|
8095
8940
|
const registered = /* @__PURE__ */ new Map();
|
|
8941
|
+
const shaderFiles = relative.filter((file) => file.endsWith(".metal"));
|
|
8942
|
+
const metalCandidates = {};
|
|
8943
|
+
if (inputs["Package.swift"] !== void 0)
|
|
8944
|
+
metalCandidates["Package.swift"] = inputs["Package.swift"];
|
|
8945
|
+
const metalInputs = /* @__PURE__ */ new Map();
|
|
8946
|
+
for (const file of shaderFiles) {
|
|
8947
|
+
const disk = byRelative.get(file);
|
|
8948
|
+
if (!disk) throw new Error(`metal source ${file} has no input file`);
|
|
8949
|
+
const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
|
|
8950
|
+
metalCandidates[key2] = "";
|
|
8951
|
+
metalInputs.set(key2, { file, disk });
|
|
8952
|
+
}
|
|
8953
|
+
const metalFiles = Object.keys(swiftMetalSourceFiles(metalCandidates));
|
|
8954
|
+
if (metalFiles.length > MAX_SWIFT_COMPILE_METAL_FILES)
|
|
8955
|
+
throw new Error("metal source pack exceeds the compile service file cap");
|
|
8956
|
+
let metalBytes = 0;
|
|
8957
|
+
for (const key2 of metalFiles) {
|
|
8958
|
+
const input = metalInputs.get(key2);
|
|
8959
|
+
if (!input) throw new Error(`metal source ${key2} has no input file`);
|
|
8960
|
+
const { file, disk } = input;
|
|
8961
|
+
const bytes = readPackageFile(
|
|
8962
|
+
project.packagePath,
|
|
8963
|
+
disk,
|
|
8964
|
+
MAX_SWIFT_COMPILE_METAL_BYTES
|
|
8965
|
+
);
|
|
8966
|
+
metalBytes += bytes.length;
|
|
8967
|
+
if (metalBytes > MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES)
|
|
8968
|
+
throw new Error("metal source pack exceeds the compile service caps");
|
|
8969
|
+
const source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
|
|
8970
|
+
bytes
|
|
8971
|
+
);
|
|
8972
|
+
const sha256 = (0, import_node_crypto7.createHash)("sha256").update(bytes).digest("hex");
|
|
8973
|
+
const bundle = swiftResourceBundleForFile(bundles, key2);
|
|
8974
|
+
if (!bundle && inputs["Package.swift"])
|
|
8975
|
+
throw new Error(`metal source ${key2} has no resource target bundle`);
|
|
8976
|
+
metalSources[key2] = {
|
|
8977
|
+
sha256,
|
|
8978
|
+
url: `${baseUrl}${RESOURCE_PATH}${sha256}.metal`,
|
|
8979
|
+
bundlePath: bundle?.path ?? "."
|
|
8980
|
+
};
|
|
8981
|
+
metalUploads[key2] = source;
|
|
8982
|
+
watched.push(file);
|
|
8983
|
+
registered.set(`${sha256}.metal`, { bytes, contentType: "text/plain; charset=utf-8" });
|
|
8984
|
+
}
|
|
8096
8985
|
let imageBytes = 0;
|
|
8097
|
-
for (const { name: name2, file, scale } of found) {
|
|
8986
|
+
for (const { name: name2, file, scale, bundlePath } of found) {
|
|
8098
8987
|
const disk = byRelative.get(file);
|
|
8099
8988
|
if (!disk) continue;
|
|
8100
8989
|
if (Object.keys(images).length >= limits.images || imageBytes + import_node_fs14.default.statSync(disk).size > limits.imageTotalBytes) {
|
|
@@ -8104,8 +8993,12 @@ function buildSwiftResourceTable(project, baseUrl) {
|
|
|
8104
8993
|
imageBytes += bytes.length;
|
|
8105
8994
|
const hash = (0, import_node_crypto7.createHash)("sha256").update(bytes).digest("hex").slice(0, 16);
|
|
8106
8995
|
const ext = import_node_path15.default.posix.extname(file).toLowerCase();
|
|
8107
|
-
table[
|
|
8108
|
-
|
|
8996
|
+
const bundle = table[bundlePath] ?? /* @__PURE__ */ Object.create(null);
|
|
8997
|
+
const variants = bundle[name2] ??= [];
|
|
8998
|
+
variants.push({ uri: `${baseUrl}${RESOURCE_PATH}${hash}${ext}`, scale });
|
|
8999
|
+
table[bundlePath] = bundle;
|
|
9000
|
+
const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
|
|
9001
|
+
images[key2] = {
|
|
8109
9002
|
file: import_node_path15.default.posix.basename(file),
|
|
8110
9003
|
data: bytes.toString("base64")
|
|
8111
9004
|
};
|
|
@@ -8127,9 +9020,9 @@ function buildSwiftResourceTable(project, baseUrl) {
|
|
|
8127
9020
|
project.resourcesPrevious = project.resourceFiles;
|
|
8128
9021
|
project.resourceFiles = registered;
|
|
8129
9022
|
}
|
|
8130
|
-
return { table, images, colors, symbols, watched };
|
|
9023
|
+
return { table, images, metalSources, metalUploads, colors, symbols, watched };
|
|
8131
9024
|
}
|
|
8132
|
-
function buildSwiftBundleFiles(packagePath, hosted) {
|
|
9025
|
+
function buildSwiftBundleFiles(packagePath, hosted, inputs) {
|
|
8133
9026
|
packagePath = import_node_fs14.default.realpathSync(packagePath);
|
|
8134
9027
|
const limits = inputLimits(hosted);
|
|
8135
9028
|
const relative = resourceCandidateFiles(packagePath).map(
|
|
@@ -8139,30 +9032,51 @@ function buildSwiftBundleFiles(packagePath, hosted) {
|
|
|
8139
9032
|
const watched = [];
|
|
8140
9033
|
let total = 0;
|
|
8141
9034
|
const xcode = xcodeLayout(packagePath);
|
|
9035
|
+
const bundles = xcode?.resourceBundles ?? swiftResourceBundles(inputs ?? packageSources(packagePath), relative);
|
|
9036
|
+
const addFile = (key2, bytes) => {
|
|
9037
|
+
if (Object.keys(files2).length >= limits.resources || bytes.length > limits.resourceBytes || total + bytes.length > limits.resourceTotalBytes)
|
|
9038
|
+
throw new Error(
|
|
9039
|
+
`swift bundle pack exceeds ${limits.resources} files / ${limits.resourceTotalBytes} bytes`
|
|
9040
|
+
);
|
|
9041
|
+
files2[key2] = bytes.toString("base64");
|
|
9042
|
+
total += bytes.length;
|
|
9043
|
+
};
|
|
8142
9044
|
if (xcode) {
|
|
8143
9045
|
const bytes = Buffer.from(xcode.app.infoPlist);
|
|
8144
9046
|
if (bytes.length > limits.resourceBytes || bytes.length > limits.resourceTotalBytes)
|
|
8145
9047
|
throw new Error("swift launch Info.plist exceeds bundle resource limits");
|
|
8146
|
-
|
|
8147
|
-
total += bytes.length;
|
|
9048
|
+
addFile("Info.plist", bytes);
|
|
8148
9049
|
if (xcode.app.infoPlistFile)
|
|
8149
9050
|
watched.push(
|
|
8150
9051
|
import_node_path15.default.relative(packagePath, xcode.app.infoPlistFile).split(import_node_path15.default.sep).join("/")
|
|
8151
9052
|
);
|
|
8152
9053
|
}
|
|
8153
|
-
|
|
8154
|
-
|
|
9054
|
+
const groups = /* @__PURE__ */ new Map();
|
|
9055
|
+
for (const file of relative) {
|
|
8155
9056
|
const disk = import_node_path15.default.join(packagePath, ...file.split("/"));
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
9057
|
+
const key2 = xcode ? xcodeInputKey(xcode, disk, file) : file;
|
|
9058
|
+
const bundle = swiftResourceBundleForFile(bundles, key2);
|
|
9059
|
+
const bundlePath = bundle?.path ?? ".";
|
|
9060
|
+
const group = groups.get(bundlePath) ?? [];
|
|
9061
|
+
group.push(file);
|
|
9062
|
+
groups.set(bundlePath, group);
|
|
9063
|
+
}
|
|
9064
|
+
for (const bundle of bundles) {
|
|
9065
|
+
if (bundle.path === ".") continue;
|
|
9066
|
+
addFile(
|
|
9067
|
+
`${bundle.path}/Info.plist`,
|
|
9068
|
+
Buffer.from(swiftResourceBundleInfoPlist(bundle))
|
|
9069
|
+
);
|
|
9070
|
+
}
|
|
9071
|
+
for (const [bundlePath, paths] of groups) {
|
|
9072
|
+
for (const { base, file } of enumerateBundleResources(paths)) {
|
|
9073
|
+
watched.push(file);
|
|
9074
|
+
const disk = import_node_path15.default.join(packagePath, ...file.split("/"));
|
|
9075
|
+
const bytes = readPackageFile(packagePath, disk, limits.resourceBytes);
|
|
9076
|
+
addFile(bundlePath === "." ? base : `${bundlePath}/${base}`, bytes);
|
|
8160
9077
|
}
|
|
8161
|
-
const bytes = readPackageFile(packagePath, disk, limits.resourceBytes);
|
|
8162
|
-
files2[base] = bytes.toString("base64");
|
|
8163
|
-
total += bytes.length;
|
|
8164
9078
|
}
|
|
8165
|
-
return { files: files2, watched };
|
|
9079
|
+
return { files: files2, bundles, watched };
|
|
8166
9080
|
}
|
|
8167
9081
|
function linkedModuleRoots(packagePath) {
|
|
8168
9082
|
packagePath = import_node_fs14.default.realpathSync(packagePath);
|
|
@@ -8208,7 +9122,20 @@ function sourceStamp(packagePath, moduleRootOverride, hosted = false) {
|
|
|
8208
9122
|
function icuUrl(origin, artifact) {
|
|
8209
9123
|
return "url" in artifact.icu ? artifact.icu.url : `${origin}${ICU_PATH}${artifact.icu.sha256}`;
|
|
8210
9124
|
}
|
|
8211
|
-
function
|
|
9125
|
+
function standinLibraries(layout) {
|
|
9126
|
+
const linked = /* @__PURE__ */ new Map();
|
|
9127
|
+
for (const binary of layout.binaries) {
|
|
9128
|
+
const modules = layout.standins.filter(
|
|
9129
|
+
(standin) => standin.target === binary.target && `${standin.module}.c` in standin.files
|
|
9130
|
+
);
|
|
9131
|
+
if (modules.length === 0) continue;
|
|
9132
|
+
const library = standinLibrary(binary, layout.app.rootDir);
|
|
9133
|
+
if (!library) continue;
|
|
9134
|
+
linked.set(library, modules);
|
|
9135
|
+
}
|
|
9136
|
+
return linked;
|
|
9137
|
+
}
|
|
9138
|
+
function packageSources(packagePath, linked = /* @__PURE__ */ new Set()) {
|
|
8212
9139
|
const xcode = xcodeLayout(packagePath);
|
|
8213
9140
|
const files2 = {};
|
|
8214
9141
|
for (const file of sourceFiles(packagePath)) {
|
|
@@ -8224,25 +9151,40 @@ function packageSources(packagePath) {
|
|
|
8224
9151
|
files2["Package.swift"] = xcodeManifest(xcode);
|
|
8225
9152
|
for (const standin of xcode.standins)
|
|
8226
9153
|
for (const [file, text3] of Object.entries(standin.files))
|
|
8227
|
-
files2[import_node_path15.default.posix.join(XCODE_STANDINS_DIR, standin.module, file)] =
|
|
9154
|
+
files2[import_node_path15.default.posix.join(XCODE_STANDINS_DIR, standin.module, file)] = linked.has(standin) && file === `${standin.module}.c` ? `// ${standin.target}'s WebAssembly library defines ${standin.module}'s functions.
|
|
9155
|
+
` : text3;
|
|
8228
9156
|
}
|
|
8229
9157
|
return files2;
|
|
8230
9158
|
}
|
|
8231
9159
|
function packageSnapshot(project, entry) {
|
|
8232
|
-
const files2 = packageSources(project.packagePath);
|
|
8233
9160
|
const layout = xcodeLayout(project.packagePath);
|
|
9161
|
+
const linked = layout ? standinLibraries(layout) : /* @__PURE__ */ new Map();
|
|
9162
|
+
const files2 = packageSources(project.packagePath, new Set([...linked.values()].flat()));
|
|
8234
9163
|
const native = nativeSourceDescriptor(project.packagePath);
|
|
8235
9164
|
return {
|
|
8236
9165
|
files: files2,
|
|
8237
9166
|
entry: layout ? xcodeInputKey(layout, import_node_path15.default.resolve(project.packagePath, entry), entry) : entry,
|
|
8238
9167
|
resourcePaths: swiftImplicitResourcePaths(
|
|
8239
|
-
resourceCandidateFiles(project.packagePath).map(
|
|
8240
|
-
|
|
8241
|
-
|
|
9168
|
+
resourceCandidateFiles(project.packagePath).map((file) => {
|
|
9169
|
+
const relative = import_node_path15.default.relative(project.packagePath, file).split(import_node_path15.default.sep).join(import_node_path15.default.posix.sep);
|
|
9170
|
+
return layout && file.endsWith(".metal") ? xcodeInputKey(layout, file, relative) : relative;
|
|
9171
|
+
})
|
|
9172
|
+
),
|
|
9173
|
+
resources: buildSwiftResourceTable(project, "", files2),
|
|
9174
|
+
bundleFiles: buildSwiftBundleFiles(
|
|
9175
|
+
project.packagePath,
|
|
9176
|
+
Boolean(project.hosted),
|
|
9177
|
+
files2
|
|
8242
9178
|
),
|
|
8243
|
-
resources: buildSwiftResourceTable(project, ""),
|
|
8244
|
-
bundleFiles: buildSwiftBundleFiles(project.packagePath, Boolean(project.hosted)),
|
|
8245
9179
|
native,
|
|
9180
|
+
...linked.size > 0 ? {
|
|
9181
|
+
libraries: Object.fromEntries(
|
|
9182
|
+
[...linked].map(([library, [first]]) => [
|
|
9183
|
+
first.module,
|
|
9184
|
+
import_node_fs14.default.readFileSync(library).toString("base64")
|
|
9185
|
+
])
|
|
9186
|
+
)
|
|
9187
|
+
} : {},
|
|
8246
9188
|
...native ? {
|
|
8247
9189
|
glue: readPackageFile(
|
|
8248
9190
|
project.packagePath,
|
|
@@ -8255,11 +9197,14 @@ function packageSnapshot(project, entry) {
|
|
|
8255
9197
|
function snapshotCompileInput(snapshot) {
|
|
8256
9198
|
const input = {
|
|
8257
9199
|
files: snapshot.files,
|
|
9200
|
+
metalSources: snapshot.resources.metalUploads,
|
|
8258
9201
|
resourcePaths: snapshot.resourcePaths,
|
|
9202
|
+
resourceBundles: snapshot.bundleFiles.bundles,
|
|
8259
9203
|
resources: snapshot.bundleFiles.files,
|
|
8260
9204
|
images: snapshot.resources.images,
|
|
8261
9205
|
entry: snapshot.entry,
|
|
8262
|
-
oneModule: true
|
|
9206
|
+
oneModule: true,
|
|
9207
|
+
...snapshot.libraries ? { libraries: snapshot.libraries } : {}
|
|
8263
9208
|
};
|
|
8264
9209
|
return snapshot.glue ? withNativeSourceGlue(input, snapshot.glue) : input;
|
|
8265
9210
|
}
|
|
@@ -8268,6 +9213,7 @@ async function compile(packagePath, stamp, moduleRootOverride, hosted, snapshot)
|
|
|
8268
9213
|
table: snapshot.resources.table,
|
|
8269
9214
|
colors: snapshot.resources.colors,
|
|
8270
9215
|
symbols: snapshot.resources.symbols,
|
|
9216
|
+
metalSources: snapshot.resources.metalSources,
|
|
8271
9217
|
watched: snapshot.resources.watched
|
|
8272
9218
|
};
|
|
8273
9219
|
const content = {
|
|
@@ -8375,12 +9321,7 @@ async function missingModulesMessage(packagePath, missing) {
|
|
|
8375
9321
|
];
|
|
8376
9322
|
}),
|
|
8377
9323
|
...[...missing.keys()].flatMap(
|
|
8378
|
-
(name2) =>
|
|
8379
|
-
[
|
|
8380
|
-
name2,
|
|
8381
|
-
{ source: "the iOS SDK", reason: UNPROVIDED_PLATFORM_MODULES[name2] }
|
|
8382
|
-
]
|
|
8383
|
-
] : IOS_SDK_FRAMEWORKS.has(name2) ? [
|
|
9324
|
+
(name2) => IOS_SDK_FRAMEWORKS.has(name2) ? [
|
|
8384
9325
|
[
|
|
8385
9326
|
name2,
|
|
8386
9327
|
{ source: "the iOS SDK", reason: "a framework Peach does not provide" }
|
|
@@ -8391,9 +9332,7 @@ async function missingModulesMessage(packagePath, missing) {
|
|
|
8391
9332
|
...layout?.packages.unavailable ?? []
|
|
8392
9333
|
]);
|
|
8393
9334
|
const packaged = new Set(
|
|
8394
|
-
[...missing.keys()].filter(
|
|
8395
|
-
(name2) => !UNPROVIDED_PLATFORM_MODULES[name2] && !IOS_SDK_FRAMEWORKS.has(name2)
|
|
8396
|
-
)
|
|
9335
|
+
[...missing.keys()].filter((name2) => !IOS_SDK_FRAMEWORKS.has(name2))
|
|
8397
9336
|
);
|
|
8398
9337
|
if (packaged.size > 0)
|
|
8399
9338
|
await Promise.all(
|
|
@@ -8452,7 +9391,9 @@ async function compileRemote(packagePath, snapshot, hosted) {
|
|
|
8452
9391
|
submit,
|
|
8453
9392
|
{
|
|
8454
9393
|
files: snapshot.files,
|
|
9394
|
+
metalSources: snapshot.resources.metalUploads,
|
|
8455
9395
|
resourcePaths: snapshot.resourcePaths,
|
|
9396
|
+
resourceBundles: snapshot.bundleFiles.bundles,
|
|
8456
9397
|
resources: snapshot.bundleFiles.files,
|
|
8457
9398
|
images: snapshot.resources.images,
|
|
8458
9399
|
entry: snapshot.entry,
|
|
@@ -8534,7 +9475,7 @@ function artifactFor(project, entry, moduleRoot) {
|
|
|
8534
9475
|
project.building = { stamp, promise: fresh };
|
|
8535
9476
|
return fresh;
|
|
8536
9477
|
}
|
|
8537
|
-
var import_node_crypto7, import_node_fs14, import_node_os8, import_node_path15, RESOURCE_PATH, ICU_PATH, SKIP_SOURCE_DIRS, NATIVE_DESCRIPTOR, NATIVE_GLUE, SwiftMissingModulesError, projects, xcodeProjects, XCODE_APP_DIR, XCODE_FRAMEWORKS_DIR, XCODE_PACKAGES_DIR, XCODE_STANDINS_DIR, CHECKOUTS_PREFIX, HOSTED_LIMITS, LOCAL_LIMITS, inputLimits, RESOURCE_CONTENT_TYPES, API_GAP_PATTERNS,
|
|
9478
|
+
var import_node_crypto7, import_node_fs14, import_node_os8, import_node_path15, RESOURCE_PATH, ICU_PATH, SKIP_SOURCE_DIRS, NATIVE_DESCRIPTOR, NATIVE_GLUE, SwiftMissingModulesError, projects, xcodeProjects, XCODE_APP_DIR, XCODE_FRAMEWORKS_DIR, XCODE_PACKAGES_DIR, XCODE_STANDINS_DIR, CHECKOUTS_PREFIX, HOSTED_LIMITS, LOCAL_LIMITS, inputLimits, RESOURCE_CONTENT_TYPES, API_GAP_PATTERNS, IOS_SDK_FRAMEWORKS;
|
|
8538
9479
|
var init_swift_host = __esm({
|
|
8539
9480
|
"src/swift-host.ts"() {
|
|
8540
9481
|
"use strict";
|
|
@@ -8550,6 +9491,7 @@ var init_swift_host = __esm({
|
|
|
8550
9491
|
init_swift_compile();
|
|
8551
9492
|
init_swift_distribution();
|
|
8552
9493
|
init_swift_package();
|
|
9494
|
+
init_swift_package_manifest();
|
|
8553
9495
|
init_swift_packages();
|
|
8554
9496
|
init_swift_source_file();
|
|
8555
9497
|
init_swift_standins();
|
|
@@ -8617,10 +9559,6 @@ var init_swift_host = __esm({
|
|
|
8617
9559
|
[/^'([^']+)' is unavailable/, (match) => match[1]],
|
|
8618
9560
|
[/^no such module '([^']+)'/, (match) => `module ${match[1]}`]
|
|
8619
9561
|
];
|
|
8620
|
-
UNPROVIDED_PLATFORM_MODULES = {
|
|
8621
|
-
Darwin: "Peach compiles for WebAssembly, which has no Darwin; C library names come through Foundation",
|
|
8622
|
-
MachO: "Peach compiles for WebAssembly, which has no Mach-O images"
|
|
8623
|
-
};
|
|
8624
9562
|
IOS_SDK_FRAMEWORKS = new Set(ios_sdk_frameworks_default.frameworks);
|
|
8625
9563
|
}
|
|
8626
9564
|
});
|
|
@@ -8784,7 +9722,7 @@ function expoEntry(units) {
|
|
|
8784
9722
|
import ExpoModulesCore
|
|
8785
9723
|
${[...new Set(units.map((unit) => unit.namespace))].map((namespace) => `import ${namespace}`).join("\n")}
|
|
8786
9724
|
|
|
8787
|
-
@main struct PeachExpoApp:
|
|
9725
|
+
@main struct PeachExpoApp: PeachPackage {
|
|
8788
9726
|
init() { MainActor.assumeIsolated { PeachExpoRuntime.register([${units.flatMap((unit) => unit.classes).join(", ")}]) } }
|
|
8789
9727
|
func view(props: JSON) -> PeachExpoNativeView { PeachExpoNativeView(props: props) }
|
|
8790
9728
|
}
|
|
@@ -8807,72 +9745,45 @@ async function compileExpoSwiftModules(root, base, publishArtifact) {
|
|
|
8807
9745
|
modules: [],
|
|
8808
9746
|
failures: []
|
|
8809
9747
|
};
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
for (const unit of units) {
|
|
8813
|
-
if (!module2) {
|
|
9748
|
+
if (!module2) {
|
|
9749
|
+
for (const unit of units)
|
|
8814
9750
|
result.failures.push({
|
|
8815
9751
|
namespace: unit.moduleId,
|
|
8816
9752
|
diagnostic: "No local Swift toolchain or distribution is available"
|
|
8817
9753
|
});
|
|
8818
|
-
|
|
8819
|
-
|
|
9754
|
+
return result;
|
|
9755
|
+
}
|
|
9756
|
+
const key2 = (0, import_node_crypto8.createHash)("sha256").update(import_node_fs15.default.realpathSync(root)).digest("hex");
|
|
9757
|
+
const failures = /* @__PURE__ */ new Map();
|
|
9758
|
+
const candidates = [];
|
|
9759
|
+
const stamps = /* @__PURE__ */ new Map();
|
|
9760
|
+
for (const unit of units) {
|
|
8820
9761
|
const packagePath = import_node_path16.default.join(import_node_os9.default.tmpdir(), "peach-expo-swift", key2, unit.moduleId);
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
result.failures.push({
|
|
8836
|
-
namespace: unit.moduleId,
|
|
8837
|
-
diagnostic: failed.diagnostic
|
|
8838
|
-
});
|
|
8839
|
-
continue;
|
|
8840
|
-
}
|
|
8841
|
-
failedCompilations.delete(packagePath);
|
|
8842
|
-
await artifactFor(projectFor(packagePath), EXPO_SWIFT_ENTRY, module2.root);
|
|
8843
|
-
linked.push(unit);
|
|
8844
|
-
} catch (error) {
|
|
8845
|
-
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
8846
|
-
const appPaths = Object.values(unit.files).flatMap((source) => {
|
|
8847
|
-
const match = /^#sourceLocation\(file: (".*"), line: 1\)$/m.exec(source);
|
|
8848
|
-
if (!match) return [];
|
|
8849
|
-
const file = JSON.parse(match[1]);
|
|
8850
|
-
return typeof file === "string" ? [file] : [];
|
|
8851
|
-
});
|
|
8852
|
-
const errors = diagnostic.match(/^.+:\d+(?::\d+)?: error:.*$/gm) ?? [];
|
|
8853
|
-
const sourceErrors = errors.filter(
|
|
8854
|
-
(line) => appPaths.some((file) => line.startsWith(`${file}:`)) && !/external macro implementation type|failed to load library plugin/.test(line)
|
|
8855
|
-
);
|
|
8856
|
-
if (publishArtifact && (sourceErrors.length === 0 || sourceErrors.length !== errors.length) && !(error instanceof SwiftMissingModulesError))
|
|
8857
|
-
throw error;
|
|
8858
|
-
if (sourceErrors.length && sourceErrors.length === errors.length && module2 && stamp && sourceStamp(packagePath, module2.root) === stamp) {
|
|
8859
|
-
failedCompilations.set(packagePath, {
|
|
8860
|
-
stamp,
|
|
8861
|
-
diagnostic: sourceErrors.join("\n")
|
|
8862
|
-
});
|
|
8863
|
-
}
|
|
8864
|
-
result.failures.push({
|
|
8865
|
-
namespace: unit.moduleId,
|
|
8866
|
-
diagnostic: sourceErrors.length ? sourceErrors.join("\n") : diagnostic
|
|
8867
|
-
});
|
|
9762
|
+
syncSwiftTree(
|
|
9763
|
+
packagePath,
|
|
9764
|
+
new Map(
|
|
9765
|
+
Object.entries(unit.files).map(([name2, source]) => [
|
|
9766
|
+
import_node_path16.default.join(packagePath, name2),
|
|
9767
|
+
source
|
|
9768
|
+
])
|
|
9769
|
+
)
|
|
9770
|
+
);
|
|
9771
|
+
const stamp = sourceStamp(packagePath, module2.root);
|
|
9772
|
+
const failed = failedCompilations.get(packagePath);
|
|
9773
|
+
if (failed?.stamp === stamp) {
|
|
9774
|
+
failures.set(unit.moduleId, failed.diagnostic);
|
|
9775
|
+
continue;
|
|
8868
9776
|
}
|
|
9777
|
+
failedCompilations.delete(packagePath);
|
|
9778
|
+
stamps.set(unit, stamp);
|
|
9779
|
+
candidates.push(unit);
|
|
8869
9780
|
}
|
|
8870
|
-
|
|
9781
|
+
const link = async (linked2) => {
|
|
8871
9782
|
const files2 = Object.assign(
|
|
8872
9783
|
{},
|
|
8873
|
-
...
|
|
9784
|
+
...linked2.map((unit) => unit.files)
|
|
8874
9785
|
);
|
|
8875
|
-
files2[EXPO_SWIFT_ENTRY] = expoEntry(
|
|
9786
|
+
files2[EXPO_SWIFT_ENTRY] = expoEntry(linked2);
|
|
8876
9787
|
const targets = [
|
|
8877
9788
|
...new Set(
|
|
8878
9789
|
Object.keys(files2).flatMap((name2) => {
|
|
@@ -8895,11 +9806,58 @@ let package = Package(name: "PeachExpo", targets: [${targets.map((name2) => `.ta
|
|
|
8895
9806
|
])
|
|
8896
9807
|
)
|
|
8897
9808
|
);
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
9809
|
+
return artifactFor(projectFor(packagePath), EXPO_SWIFT_ENTRY, module2.root);
|
|
9810
|
+
};
|
|
9811
|
+
let linked = candidates;
|
|
9812
|
+
let artifact;
|
|
9813
|
+
if (linked.length) {
|
|
9814
|
+
try {
|
|
9815
|
+
artifact = await link(linked);
|
|
9816
|
+
} catch (linkError) {
|
|
9817
|
+
linked = [];
|
|
9818
|
+
for (const unit of candidates) {
|
|
9819
|
+
const packagePath = import_node_path16.default.join(import_node_os9.default.tmpdir(), "peach-expo-swift", key2, unit.moduleId);
|
|
9820
|
+
try {
|
|
9821
|
+
await artifactFor(projectFor(packagePath), EXPO_SWIFT_ENTRY, module2.root);
|
|
9822
|
+
linked.push(unit);
|
|
9823
|
+
} catch (error) {
|
|
9824
|
+
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
9825
|
+
const appPaths = Object.values(unit.files).flatMap((source) => {
|
|
9826
|
+
const match = /^#sourceLocation\(file: (".*"), line: 1\)$/m.exec(source);
|
|
9827
|
+
if (!match) return [];
|
|
9828
|
+
const file = JSON.parse(match[1]);
|
|
9829
|
+
return typeof file === "string" ? [file] : [];
|
|
9830
|
+
});
|
|
9831
|
+
const errors = diagnostic.match(/^.+:\d+(?::\d+)?: error:.*$/gm) ?? [];
|
|
9832
|
+
const sourceErrors = errors.filter(
|
|
9833
|
+
(line) => appPaths.some((file) => line.startsWith(`${file}:`)) && !/external macro implementation type|failed to load library plugin/.test(
|
|
9834
|
+
line
|
|
9835
|
+
)
|
|
9836
|
+
);
|
|
9837
|
+
if (publishArtifact && (sourceErrors.length === 0 || sourceErrors.length !== errors.length) && !(error instanceof SwiftMissingModulesError))
|
|
9838
|
+
throw error;
|
|
9839
|
+
if (sourceErrors.length && sourceErrors.length === errors.length && sourceStamp(packagePath, module2.root) === stamps.get(unit)) {
|
|
9840
|
+
failedCompilations.set(packagePath, {
|
|
9841
|
+
stamp: stamps.get(unit),
|
|
9842
|
+
diagnostic: sourceErrors.join("\n")
|
|
9843
|
+
});
|
|
9844
|
+
}
|
|
9845
|
+
failures.set(
|
|
9846
|
+
unit.moduleId,
|
|
9847
|
+
sourceErrors.length ? sourceErrors.join("\n") : diagnostic
|
|
9848
|
+
);
|
|
9849
|
+
}
|
|
9850
|
+
}
|
|
9851
|
+
if (linked.length === candidates.length) throw linkError;
|
|
9852
|
+
if (linked.length) artifact = await link(linked);
|
|
9853
|
+
}
|
|
9854
|
+
}
|
|
9855
|
+
for (const unit of units) {
|
|
9856
|
+
const diagnostic = failures.get(unit.moduleId);
|
|
9857
|
+
if (diagnostic !== void 0)
|
|
9858
|
+
result.failures.push({ namespace: unit.moduleId, diagnostic });
|
|
9859
|
+
}
|
|
9860
|
+
if (artifact) {
|
|
8903
9861
|
await publishArtifact?.(artifact);
|
|
8904
9862
|
result.modules.push({
|
|
8905
9863
|
namespaces: linked.map((unit) => unit.moduleId),
|
|
@@ -8966,114 +9924,1387 @@ var init_expo_swift_bundle = __esm({
|
|
|
8966
9924
|
}
|
|
8967
9925
|
});
|
|
8968
9926
|
|
|
8969
|
-
// src/
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
snapshotOneDevBundle: () => snapshotOneDevBundle
|
|
8975
|
-
});
|
|
8976
|
-
module.exports = __toCommonJS(bundle_channel_exports);
|
|
8977
|
-
var import_node_crypto9 = require("node:crypto");
|
|
8978
|
-
var import_node_vm = require("node:vm");
|
|
8979
|
-
|
|
8980
|
-
// ../contrast/src/runtime/process-group.ts
|
|
8981
|
-
var import_node_child_process = require("node:child_process");
|
|
8982
|
-
|
|
8983
|
-
// ../contrast/src/sleep.ts
|
|
8984
|
-
function sleep(ms) {
|
|
8985
|
-
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
9927
|
+
// src/kotlin-view-models.ts
|
|
9928
|
+
function strings2(value) {
|
|
9929
|
+
if (!Array.isArray(value) || !value.every((item) => typeof item === "string"))
|
|
9930
|
+
throw new Error("abi-classes printed an invalid list");
|
|
9931
|
+
return value;
|
|
8986
9932
|
}
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9933
|
+
function readAbiClasses(output) {
|
|
9934
|
+
return output.split("\n").filter((line) => line.startsWith("{")).map((line) => {
|
|
9935
|
+
const row = JSON.parse(line);
|
|
9936
|
+
if (!isRecord(row) || typeof row.name !== "string" || typeof row.kind !== "string" || typeof row.modality !== "string" || typeof row.inner !== "boolean" || typeof row.generic !== "boolean" || !Array.isArray(row.constructors))
|
|
9937
|
+
throw new Error(`abi-classes printed an invalid class: ${line}`);
|
|
9938
|
+
return {
|
|
9939
|
+
name: row.name,
|
|
9940
|
+
kind: row.kind,
|
|
9941
|
+
modality: row.modality,
|
|
9942
|
+
inner: row.inner,
|
|
9943
|
+
generic: row.generic,
|
|
9944
|
+
supers: strings2(row.supers),
|
|
9945
|
+
constructors: row.constructors.map((constructor) => {
|
|
9946
|
+
if (!isRecord(constructor) || typeof constructor.defaulted !== "boolean")
|
|
9947
|
+
throw new Error(`abi-classes printed an invalid constructor: ${line}`);
|
|
9948
|
+
return {
|
|
9949
|
+
parameters: strings2(constructor.parameters),
|
|
9950
|
+
defaulted: constructor.defaulted
|
|
9951
|
+
};
|
|
9952
|
+
})
|
|
9953
|
+
};
|
|
9954
|
+
});
|
|
9955
|
+
}
|
|
9956
|
+
function matching(row, signature) {
|
|
9957
|
+
for (const { parameters } of row.constructors) {
|
|
9958
|
+
if (parameters.join() === signature.join()) return "match";
|
|
9959
|
+
if (parameters.length === signature.length && signature.every((type) => parameters.includes(type)))
|
|
9960
|
+
return "misordered";
|
|
9000
9961
|
}
|
|
9962
|
+
return null;
|
|
9001
9963
|
}
|
|
9002
|
-
function
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
}
|
|
9008
|
-
|
|
9964
|
+
function signatureOf(row, android) {
|
|
9965
|
+
const handled = matching(row, android ? [APPLICATION2, HANDLE] : [HANDLE]);
|
|
9966
|
+
if (handled === "misordered") return "misordered";
|
|
9967
|
+
if (handled) return android ? "application-handle" : "handle";
|
|
9968
|
+
if (android)
|
|
9969
|
+
return row.constructors.some(({ parameters }) => parameters.join() === APPLICATION2) ? "application" : null;
|
|
9970
|
+
return row.constructors.some(
|
|
9971
|
+
({ parameters, defaulted }) => parameters.length === 0 || defaulted
|
|
9972
|
+
) ? "none" : null;
|
|
9973
|
+
}
|
|
9974
|
+
function viewModelClasses(rows) {
|
|
9975
|
+
const byName = new Map(rows.map((row) => [row.name, row]));
|
|
9976
|
+
const base = (row, seen) => {
|
|
9977
|
+
for (const name2 of row.supers) {
|
|
9978
|
+
if (name2 === VIEW_MODEL || name2 === ANDROID_VIEW_MODEL) return name2;
|
|
9979
|
+
const parent = byName.get(name2);
|
|
9980
|
+
if (parent && !seen.has(name2)) {
|
|
9981
|
+
seen.add(name2);
|
|
9982
|
+
const found = base(parent, seen);
|
|
9983
|
+
if (found) return found;
|
|
9984
|
+
}
|
|
9009
9985
|
}
|
|
9986
|
+
return null;
|
|
9987
|
+
};
|
|
9988
|
+
return rows.flatMap((row) => {
|
|
9989
|
+
if (row.kind !== "CLASS" || row.inner || row.generic) return [];
|
|
9990
|
+
if (row.modality === "ABSTRACT" || row.modality === "SEALED") return [];
|
|
9991
|
+
const root = base(row, /* @__PURE__ */ new Set());
|
|
9992
|
+
if (!root) return [];
|
|
9993
|
+
const signature = signatureOf(row, root === ANDROID_VIEW_MODEL);
|
|
9994
|
+
return signature ? [{ name: row.name, signature }] : [];
|
|
9010
9995
|
});
|
|
9011
9996
|
}
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9997
|
+
var VIEW_MODEL, ANDROID_VIEW_MODEL, APPLICATION2, HANDLE;
|
|
9998
|
+
var init_kotlin_view_models = __esm({
|
|
9999
|
+
"src/kotlin-view-models.ts"() {
|
|
10000
|
+
"use strict";
|
|
10001
|
+
init_is_record();
|
|
10002
|
+
VIEW_MODEL = "androidx.lifecycle.ViewModel";
|
|
10003
|
+
ANDROID_VIEW_MODEL = "androidx.lifecycle.AndroidViewModel";
|
|
10004
|
+
APPLICATION2 = "android.app.Application";
|
|
10005
|
+
HANDLE = "androidx.lifecycle.SavedStateHandle";
|
|
9018
10006
|
}
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
10007
|
+
});
|
|
10008
|
+
|
|
10009
|
+
// src/kotlin-host.ts
|
|
10010
|
+
var kotlin_host_exports = {};
|
|
10011
|
+
__export(kotlin_host_exports, {
|
|
10012
|
+
expoKotlinArtifact: () => expoKotlinArtifact,
|
|
10013
|
+
kotlinAppArtifact: () => kotlinAppArtifact,
|
|
10014
|
+
kotlinArtifact: () => kotlinArtifact,
|
|
10015
|
+
kotlinArtifactFiles: () => kotlinArtifactFiles,
|
|
10016
|
+
kotlinSources: () => kotlinSources,
|
|
10017
|
+
peachKotlinModuleRoot: () => peachKotlinModuleRoot,
|
|
10018
|
+
serveKotlinArtifact: () => serveKotlinArtifact,
|
|
10019
|
+
serveKotlinRequest: () => serveKotlinRequest
|
|
10020
|
+
});
|
|
10021
|
+
function readToolchain(moduleRoot) {
|
|
10022
|
+
const parsed = JSON.parse(
|
|
10023
|
+
import_node_fs16.default.readFileSync(import_node_path17.default.join(moduleRoot, "toolchain.json"), "utf8")
|
|
10024
|
+
);
|
|
10025
|
+
const download = (value) => {
|
|
10026
|
+
if (!isRecord(value) || typeof value.url !== "string" || typeof value.sha256 !== "string")
|
|
10027
|
+
throw new Error(
|
|
10028
|
+
"peachsim kotlin/toolchain.json names a download without url and sha256"
|
|
10029
|
+
);
|
|
10030
|
+
return { url: value.url, sha256: value.sha256 };
|
|
10031
|
+
};
|
|
10032
|
+
if (!isRecord(parsed) || !isRecord(parsed.compiler) || !Array.isArray(parsed.libraries) || !Array.isArray(parsed.composeLibraries) || !Array.isArray(parsed.composeJsLibraries) || !isRecord(parsed.composeRuntime) || typeof parsed.composeRuntime.name !== "string")
|
|
10033
|
+
throw new Error("peachsim kotlin/toolchain.json has no compiler and libraries");
|
|
10034
|
+
const version = parsed.compiler.version;
|
|
10035
|
+
if (typeof version !== "string")
|
|
10036
|
+
throw new Error("peachsim kotlin/toolchain.json has no compiler version");
|
|
10037
|
+
const libraries = (values) => values.map((library) => {
|
|
10038
|
+
if (!isRecord(library) || typeof library.name !== "string")
|
|
10039
|
+
throw new Error("peachsim kotlin/toolchain.json names a library without a name");
|
|
10040
|
+
return { ...download(library), name: library.name };
|
|
9022
10041
|
});
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
10042
|
+
return {
|
|
10043
|
+
compiler: { ...download(parsed.compiler), version },
|
|
10044
|
+
libraries: libraries(parsed.libraries),
|
|
10045
|
+
composeLibraries: libraries(parsed.composeLibraries),
|
|
10046
|
+
composeRuntime: {
|
|
10047
|
+
...download(parsed.composeRuntime),
|
|
10048
|
+
name: parsed.composeRuntime.name
|
|
10049
|
+
},
|
|
10050
|
+
composeJsLibraries: parsed.composeJsLibraries.map((library) => {
|
|
10051
|
+
if (!isRecord(library) || typeof library.name !== "string" || typeof library.module !== "string" || typeof library.file !== "string" || typeof library.archiveEntry !== "string")
|
|
10052
|
+
throw new Error("peachsim kotlin/toolchain.json has an incomplete JS library");
|
|
10053
|
+
return {
|
|
10054
|
+
...download(library),
|
|
10055
|
+
name: library.name,
|
|
10056
|
+
module: library.module,
|
|
10057
|
+
file: library.file,
|
|
10058
|
+
archiveEntry: library.archiveEntry
|
|
10059
|
+
};
|
|
10060
|
+
})
|
|
10061
|
+
};
|
|
10062
|
+
}
|
|
10063
|
+
function kotlinHome() {
|
|
10064
|
+
return import_node_path17.default.join(rnxHomeDir(), "kotlin");
|
|
10065
|
+
}
|
|
10066
|
+
async function fetchVerified(download, target) {
|
|
10067
|
+
if (import_node_fs16.default.existsSync(target)) return;
|
|
10068
|
+
const response = await fetch(download.url);
|
|
10069
|
+
if (!response.ok) throw new Error(`${download.url} answered ${response.status}`);
|
|
10070
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
10071
|
+
const digest2 = (0, import_node_crypto9.createHash)("sha256").update(bytes).digest("hex");
|
|
10072
|
+
if (digest2 !== download.sha256)
|
|
10073
|
+
throw new Error(`${download.url} has sha256 ${digest2}, expected ${download.sha256}`);
|
|
10074
|
+
import_node_fs16.default.mkdirSync(import_node_path17.default.dirname(target), { recursive: true });
|
|
10075
|
+
const partial = `${target}.${process.pid}.partial`;
|
|
10076
|
+
import_node_fs16.default.writeFileSync(partial, bytes);
|
|
10077
|
+
import_node_fs16.default.renameSync(partial, target);
|
|
10078
|
+
}
|
|
10079
|
+
function ensureToolchain(toolchain) {
|
|
10080
|
+
toolchainReady ??= (async () => {
|
|
10081
|
+
const dir = import_node_path17.default.join(kotlinHome(), toolchain.compiler.version);
|
|
10082
|
+
const kotlinc = import_node_path17.default.join(dir, "kotlinc", "bin", "kotlinc-wasm");
|
|
10083
|
+
if (!import_node_fs16.default.existsSync(kotlinc)) {
|
|
10084
|
+
const zip = import_node_path17.default.join(dir, "kotlin-compiler.zip");
|
|
10085
|
+
await fetchVerified(toolchain.compiler, zip);
|
|
10086
|
+
await run4("unzip", ["-q", "-o", zip, "-d", dir]);
|
|
10087
|
+
import_node_fs16.default.rmSync(zip);
|
|
10088
|
+
}
|
|
10089
|
+
const java = process.env.JAVA_HOME ? import_node_path17.default.join(process.env.JAVA_HOME, "bin", "java") : "java";
|
|
10090
|
+
await run4(java, ["-version"]).catch(() => {
|
|
10091
|
+
throw new Error(
|
|
10092
|
+
`Kotlin in Peach compiles with kotlinc, which needs a Java runtime (17 or newer, as android builds use); ${process.env.JAVA_HOME ? `JAVA_HOME ${process.env.JAVA_HOME} has none` : "set JAVA_HOME or put java on PATH"}`
|
|
10093
|
+
);
|
|
10094
|
+
});
|
|
10095
|
+
const libraries = [import_node_path17.default.join(dir, "kotlinc", "lib", "kotlin-stdlib-wasm-js.klib")];
|
|
10096
|
+
for (const library of toolchain.libraries) {
|
|
10097
|
+
const target = import_node_path17.default.join(dir, library.name);
|
|
10098
|
+
await fetchVerified(library, target);
|
|
10099
|
+
libraries.push(target);
|
|
10100
|
+
}
|
|
10101
|
+
return { kotlinc, libraries };
|
|
10102
|
+
})().catch((error) => {
|
|
10103
|
+
toolchainReady = void 0;
|
|
10104
|
+
throw error;
|
|
9027
10105
|
});
|
|
10106
|
+
return toolchainReady;
|
|
9028
10107
|
}
|
|
9029
|
-
|
|
9030
|
-
const
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
10108
|
+
function appKotlinLanguage(root) {
|
|
10109
|
+
const reactNative = import_node_path17.default.dirname(
|
|
10110
|
+
(0, import_node_module2.createRequire)(import_node_path17.default.join(root, "package.json")).resolve("react-native/package.json")
|
|
10111
|
+
);
|
|
10112
|
+
const versions = import_node_fs16.default.readFileSync(
|
|
10113
|
+
import_node_path17.default.join(reactNative, "gradle", "libs.versions.toml"),
|
|
10114
|
+
"utf8"
|
|
10115
|
+
);
|
|
10116
|
+
const match = /^kotlin\s*=\s*"(\d+)\.(\d+)/m.exec(versions);
|
|
10117
|
+
if (!match)
|
|
10118
|
+
throw new Error(`${reactNative}/gradle/libs.versions.toml names no kotlin version`);
|
|
10119
|
+
return `${match[1]}.${match[2]}`;
|
|
9037
10120
|
}
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
signalProcessGroup(child, "SIGSTOP");
|
|
9047
|
-
const descendants = /* @__PURE__ */ new Set();
|
|
9048
|
-
let parents = [child.pid];
|
|
9049
|
-
let inspectionError = null;
|
|
9050
|
-
while (parents.length > 0) {
|
|
9051
|
-
const result = (0, import_node_child_process.spawnSync)("pgrep", ["-P", parents.join(",")], {
|
|
9052
|
-
encoding: "utf8",
|
|
9053
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
9054
|
-
});
|
|
9055
|
-
if (result.error || result.status !== 0 && result.status !== 1) {
|
|
9056
|
-
inspectionError = new Error(
|
|
9057
|
-
`could not inspect descendants of processes ${parents.join(",")}: ${result.error?.message || result.stderr.trim() || `pgrep exited ${result.status}`}`
|
|
9058
|
-
);
|
|
9059
|
-
break;
|
|
9060
|
-
}
|
|
9061
|
-
const next = [];
|
|
9062
|
-
for (const line of result.stdout.split("\n")) {
|
|
9063
|
-
const descendantPid = Number(line.trim());
|
|
9064
|
-
if (Number.isInteger(descendantPid) && descendantPid > 1 && !descendants.has(descendantPid)) {
|
|
9065
|
-
descendants.add(descendantPid);
|
|
9066
|
-
next.push(descendantPid);
|
|
9067
|
-
try {
|
|
9068
|
-
process.kill(descendantPid, "SIGSTOP");
|
|
9069
|
-
} catch {
|
|
9070
|
-
}
|
|
9071
|
-
}
|
|
10121
|
+
function kotlinSources(root, skip = SKIP_DIRS) {
|
|
10122
|
+
const sources = [];
|
|
10123
|
+
const walk2 = (dir) => {
|
|
10124
|
+
for (const entry of import_node_fs16.default.readdirSync(dir, { withFileTypes: true })) {
|
|
10125
|
+
if (entry.name.startsWith(".") || skip.has(entry.name)) continue;
|
|
10126
|
+
const full = import_node_path17.default.join(dir, entry.name);
|
|
10127
|
+
if (entry.isDirectory()) walk2(full);
|
|
10128
|
+
else if (entry.isFile() && entry.name.endsWith(".kt")) sources.push(full);
|
|
9072
10129
|
}
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
10130
|
+
};
|
|
10131
|
+
walk2(root);
|
|
10132
|
+
return sources.sort();
|
|
10133
|
+
}
|
|
10134
|
+
function entrySource(ids) {
|
|
10135
|
+
return [
|
|
10136
|
+
"import android.os.Build",
|
|
10137
|
+
"import kotlin.js.JsAny",
|
|
10138
|
+
"import kotlin.js.Promise",
|
|
10139
|
+
"import kotlinx.coroutines.Dispatchers",
|
|
10140
|
+
"import kotlinx.coroutines.GlobalScope",
|
|
10141
|
+
"import kotlinx.coroutines.promise",
|
|
10142
|
+
"import dev.onejs.one.OneNativeSourceDispatch",
|
|
10143
|
+
"import org.json.JSONObject",
|
|
10144
|
+
"",
|
|
10145
|
+
"private val instances = mutableMapOf<String, OneNativeSourceDispatch>()",
|
|
10146
|
+
"",
|
|
10147
|
+
"private fun dispatcher(packageName: String): OneNativeSourceDispatch? = instances[packageName] ?: when (packageName) {",
|
|
10148
|
+
...ids.map((id) => ` ${JSON.stringify(id)} -> OneNativeSource_${id}()`),
|
|
10149
|
+
" else -> null",
|
|
10150
|
+
"}?.also { instances[packageName] = it }",
|
|
10151
|
+
"",
|
|
10152
|
+
"@OptIn(kotlin.js.ExperimentalJsExport::class)",
|
|
10153
|
+
"@JsExport",
|
|
10154
|
+
"fun peachSetAndroidBuildInfo(model: String, release: String) = Build.setDevice(model, release)",
|
|
10155
|
+
"",
|
|
10156
|
+
"@OptIn(kotlin.js.ExperimentalJsExport::class, kotlin.js.ExperimentalWasmJsInterop::class, kotlinx.coroutines.DelicateCoroutinesApi::class)",
|
|
10157
|
+
"@JsExport",
|
|
10158
|
+
"fun peachNativeCall(module: String, method: String, argsJson: String, contractHash: String): Promise<JsAny?> =",
|
|
10159
|
+
" GlobalScope.promise(Dispatchers.Main) {",
|
|
10160
|
+
" val reply = JSONObject()",
|
|
10161
|
+
" try {",
|
|
10162
|
+
` val packageName = module.substringBefore('.', "")`,
|
|
10163
|
+
" val dispatch = dispatcher(packageName)",
|
|
10164
|
+
" if (packageName.isEmpty() || !module.contains('.')) {",
|
|
10165
|
+
' reply.put("ok", false).put("code", "E_NATIVE_SOURCE").put("error", "invalid module $module")',
|
|
10166
|
+
" } else if (dispatch == null) {",
|
|
10167
|
+
' reply.put("ok", false).put("code", "E_NATIVE_SOURCE").put("error", "$module.$method: OneNativeSource_$packageName")',
|
|
10168
|
+
" } else if (dispatch.contractHash != contractHash) {",
|
|
10169
|
+
' reply.put("ok", false).put("code", "E_NATIVE_SOURCE_REBUILD").put("error", "native module $module changed; rebuild the app")',
|
|
10170
|
+
" } else {",
|
|
10171
|
+
' reply.put("ok", true).put("value", dispatch.call(module, method, argsJson))',
|
|
10172
|
+
" }",
|
|
10173
|
+
" } catch (error: Throwable) {",
|
|
10174
|
+
' reply.put("ok", false).put("code", "E_NATIVE_SOURCE").put("error", "$module.$method: ${error.message}")',
|
|
10175
|
+
" }",
|
|
10176
|
+
" reply.toString().toJsString()",
|
|
10177
|
+
" }",
|
|
10178
|
+
""
|
|
10179
|
+
].join("\n");
|
|
10180
|
+
}
|
|
10181
|
+
function buildsDir() {
|
|
10182
|
+
return import_node_path17.default.join(kotlinHome(), "builds");
|
|
10183
|
+
}
|
|
10184
|
+
async function kotlinArtifact(root, moduleRoot, origin) {
|
|
10185
|
+
const { kotlinSourceId, nativeSourceContract, renderKotlinSourceGlue } = await import("vxrn/native-source-contract");
|
|
10186
|
+
const toolchain = readToolchain(moduleRoot);
|
|
10187
|
+
const language = appKotlinLanguage(root);
|
|
10188
|
+
const sources = kotlinSources(root);
|
|
10189
|
+
if (sources.length === 0) throw new Error(`${root} holds no Kotlin sources`);
|
|
10190
|
+
const generated = {};
|
|
10191
|
+
const ids = [];
|
|
10192
|
+
const viewIds = [];
|
|
10193
|
+
let usesCompose = false;
|
|
10194
|
+
for (const file of sources) {
|
|
10195
|
+
const source = import_node_fs16.default.readFileSync(file, "utf8");
|
|
10196
|
+
if (/\bandroidx\.compose\./.test(source)) usesCompose = true;
|
|
10197
|
+
const contract = nativeSourceContract(file, source);
|
|
10198
|
+
if (contract.modules.length === 0 && contract.views.length === 0) continue;
|
|
10199
|
+
const id = kotlinSourceId(root, file);
|
|
10200
|
+
if (contract.modules.length > 0) ids.push(id);
|
|
10201
|
+
if (contract.views.length > 0) viewIds.push(id);
|
|
10202
|
+
generated[`OneNativeSource_${id}.kt`] = renderKotlinSourceGlue(id, contract).source;
|
|
10203
|
+
}
|
|
10204
|
+
generated["PeachEntry.kt"] = entrySource(ids);
|
|
10205
|
+
if (viewIds.length > 0) generated["PeachViews.kt"] = viewsSource(viewIds);
|
|
10206
|
+
const shims = kotlinSources(import_node_path17.default.join(moduleRoot, "Sources"), /* @__PURE__ */ new Set()).filter(
|
|
10207
|
+
(file) => usesCompose || !file.endsWith("/OneNativeSourceViewDispatch.kt")
|
|
10208
|
+
);
|
|
10209
|
+
if (viewIds.length > 0)
|
|
10210
|
+
shims.push(...kotlinSources(import_node_path17.default.join(moduleRoot, "ComposeSources")));
|
|
10211
|
+
return compileKotlin(
|
|
10212
|
+
{ root, toolchain, language, sources, generated, shims, usesCompose },
|
|
10213
|
+
origin
|
|
10214
|
+
);
|
|
10215
|
+
}
|
|
10216
|
+
function readExpoField(value) {
|
|
10217
|
+
if (!isRecord(value) || typeof value.name !== "string" || typeof value.key !== "string" || typeof value.required !== "boolean" || typeof value.mutable !== "boolean" || typeof value.hidden !== "boolean")
|
|
10218
|
+
throw new Error("expo-types printed an invalid field");
|
|
10219
|
+
const range2 = value.initializer;
|
|
10220
|
+
if (range2 !== null && (!Array.isArray(range2) || range2.length !== 2 || typeof range2[0] !== "number" || typeof range2[1] !== "number"))
|
|
10221
|
+
throw new Error("expo-types printed an invalid initializer range");
|
|
10222
|
+
return {
|
|
10223
|
+
name: value.name,
|
|
10224
|
+
key: value.key,
|
|
10225
|
+
required: value.required,
|
|
10226
|
+
mutable: value.mutable,
|
|
10227
|
+
hidden: value.hidden,
|
|
10228
|
+
initializer: range2 === null ? null : [range2[0], range2[1]]
|
|
10229
|
+
};
|
|
10230
|
+
}
|
|
10231
|
+
function readExpoTypes(output) {
|
|
10232
|
+
return output.split("\n").filter((line) => line.startsWith("{")).map((line) => {
|
|
10233
|
+
const row = JSON.parse(line);
|
|
10234
|
+
if (!isRecord(row) || typeof row.file !== "string" || typeof row.package !== "string" || !Array.isArray(row.records) || !Array.isArray(row.enums) || !Array.isArray(row.views) || !Array.isArray(row.props))
|
|
10235
|
+
throw new Error("expo-types printed an invalid file");
|
|
10236
|
+
return {
|
|
10237
|
+
file: row.file,
|
|
10238
|
+
package: row.package,
|
|
10239
|
+
records: row.records.map((record4) => {
|
|
10240
|
+
if (!isRecord(record4) || typeof record4.name !== "string" || typeof record4.hidden !== "boolean" || !Array.isArray(record4.fields))
|
|
10241
|
+
throw new Error("expo-types printed an invalid record");
|
|
10242
|
+
return {
|
|
10243
|
+
name: record4.name,
|
|
10244
|
+
hidden: record4.hidden,
|
|
10245
|
+
fields: record4.fields.map(readExpoField)
|
|
10246
|
+
};
|
|
10247
|
+
}),
|
|
10248
|
+
enums: row.enums.map((entry) => {
|
|
10249
|
+
if (!isRecord(entry) || typeof entry.name !== "string" || typeof entry.hidden !== "boolean" || typeof entry.fields !== "number" || entry.parameter !== null && typeof entry.parameter !== "string" || typeof entry.hiddenParameter !== "boolean")
|
|
10250
|
+
throw new Error("expo-types printed an invalid enum");
|
|
10251
|
+
return {
|
|
10252
|
+
name: entry.name,
|
|
10253
|
+
hidden: entry.hidden,
|
|
10254
|
+
fields: entry.fields,
|
|
10255
|
+
parameter: entry.parameter,
|
|
10256
|
+
hiddenParameter: entry.hiddenParameter
|
|
10257
|
+
};
|
|
10258
|
+
}),
|
|
10259
|
+
views: row.views.map((view) => {
|
|
10260
|
+
if (!isRecord(view) || typeof view.name !== "string" || typeof view.hidden !== "boolean" || typeof view.props !== "string")
|
|
10261
|
+
throw new Error("expo-types printed an invalid view");
|
|
10262
|
+
return { name: view.name, hidden: view.hidden, props: view.props };
|
|
10263
|
+
}),
|
|
10264
|
+
props: row.props.map((entry) => {
|
|
10265
|
+
if (!isRecord(entry) || typeof entry.name !== "string" || typeof entry.hidden !== "boolean" || !Array.isArray(entry.states) || !entry.states.every((state) => typeof state === "string"))
|
|
10266
|
+
throw new Error("expo-types printed invalid compose props");
|
|
10267
|
+
return { name: entry.name, hidden: entry.hidden, states: entry.states };
|
|
10268
|
+
})
|
|
10269
|
+
};
|
|
10270
|
+
});
|
|
10271
|
+
}
|
|
10272
|
+
function scanExpoTypes(toolchain, script, sources) {
|
|
10273
|
+
const candidates = sources.filter(
|
|
10274
|
+
(file) => /\bRecord\b|\benum\s+class\b|\bExpoComposeView\b|\bExpoView\b|\bComposeProps\b/.test(
|
|
10275
|
+
import_node_fs16.default.readFileSync(file, "utf8")
|
|
10276
|
+
)
|
|
10277
|
+
);
|
|
10278
|
+
if (candidates.length === 0) return Promise.resolve([]);
|
|
10279
|
+
const digest2 = (0, import_node_crypto9.createHash)("sha256");
|
|
10280
|
+
for (const file of [script, ...candidates])
|
|
10281
|
+
digest2.update(`${file}\0${import_node_fs16.default.readFileSync(file, "utf8")}\0`);
|
|
10282
|
+
const key2 = digest2.digest("hex");
|
|
10283
|
+
let scan = expoTypeScans.get(key2);
|
|
10284
|
+
if (!scan) {
|
|
10285
|
+
scan = (async () => {
|
|
10286
|
+
const { kotlinc } = await ensureToolchain(toolchain);
|
|
10287
|
+
const { stdout } = await run4(
|
|
10288
|
+
import_node_path17.default.join(import_node_path17.default.dirname(kotlinc), "kotlinc"),
|
|
10289
|
+
[
|
|
10290
|
+
"-cp",
|
|
10291
|
+
import_node_path17.default.resolve(import_node_path17.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
|
|
10292
|
+
"-script",
|
|
10293
|
+
script,
|
|
10294
|
+
...candidates
|
|
10295
|
+
],
|
|
10296
|
+
{ maxBuffer: 16 * 1024 * 1024 }
|
|
10297
|
+
);
|
|
10298
|
+
return readExpoTypes(stdout);
|
|
10299
|
+
})().catch((error) => {
|
|
10300
|
+
expoTypeScans.delete(key2);
|
|
10301
|
+
throw error;
|
|
10302
|
+
});
|
|
10303
|
+
expoTypeScans.set(key2, scan);
|
|
10304
|
+
}
|
|
10305
|
+
return scan;
|
|
10306
|
+
}
|
|
10307
|
+
function expoTypeSources(files2) {
|
|
10308
|
+
const generated = {};
|
|
10309
|
+
const origins = {};
|
|
10310
|
+
const registrations = [];
|
|
10311
|
+
files2.forEach((file, index) => {
|
|
10312
|
+
const edits = [];
|
|
10313
|
+
const calls = [];
|
|
10314
|
+
for (const record4 of file.records) {
|
|
10315
|
+
const fields = [];
|
|
10316
|
+
for (const field of record4.fields) {
|
|
10317
|
+
if (field.initializer)
|
|
10318
|
+
edits.push({ range: field.initializer, owner: record4.name, field });
|
|
10319
|
+
if (field.hidden) {
|
|
10320
|
+
if (!field.initializer)
|
|
10321
|
+
throw new Error(
|
|
10322
|
+
`${file.file}: @Field ${record4.name}.${field.name} is private and has no initializer, which Peach cannot set`
|
|
10323
|
+
);
|
|
10324
|
+
continue;
|
|
10325
|
+
}
|
|
10326
|
+
const name2 = literal(field.key);
|
|
10327
|
+
const read = `{ record: ${record4.name} -> record.${field.name} }`;
|
|
10328
|
+
const write = field.mutable && !field.initializer ? `{ record, value -> record.${field.name} = value }` : "null";
|
|
10329
|
+
fields.push(
|
|
10330
|
+
` dev.peach.expo.PeachExpoTypes.field(${name2}, ${field.required}, ${read}, ${write}),`
|
|
10331
|
+
);
|
|
10332
|
+
}
|
|
10333
|
+
if (record4.hidden) continue;
|
|
10334
|
+
calls.push(
|
|
10335
|
+
[
|
|
10336
|
+
` dev.peach.expo.PeachExpoTypes.record(${record4.name}::class, ${literal(file.package ? `${file.package}.${record4.name}` : record4.name)}, { ${record4.name}() }, listOf(`,
|
|
10337
|
+
...fields,
|
|
10338
|
+
" ))"
|
|
10339
|
+
].join("\n")
|
|
10340
|
+
);
|
|
10341
|
+
}
|
|
10342
|
+
for (const entry of file.enums) {
|
|
10343
|
+
if (entry.hidden) continue;
|
|
10344
|
+
if (entry.hiddenParameter)
|
|
10345
|
+
throw new Error(
|
|
10346
|
+
`${file.file}: enum ${entry.name} keeps its value in a private property, which Peach cannot read`
|
|
10347
|
+
);
|
|
10348
|
+
const value = entry.fields === 1 ? `{ it.${entry.parameter} }` : "null";
|
|
10349
|
+
calls.push(
|
|
10350
|
+
` dev.peach.expo.PeachExpoTypes.enum(${entry.name}::class, enumValues<${entry.name}>(), ${entry.fields}, ${entry.parameter === null ? "null" : literal(entry.parameter)}, ${value})`
|
|
10351
|
+
);
|
|
10352
|
+
}
|
|
10353
|
+
const views = [
|
|
10354
|
+
...file.views.filter((view) => !view.hidden).map(
|
|
10355
|
+
(view) => ` dev.peach.expo.PeachExpoTypes.view(${view.name}::class, ${view.props ? `${view.props}::class` : "null"}) { context, appContext -> ${view.name}(context, appContext) }`
|
|
10356
|
+
),
|
|
10357
|
+
...file.props.filter((entry) => !entry.hidden).map(
|
|
10358
|
+
(entry) => [
|
|
10359
|
+
` dev.peach.expo.PeachExpoTypes.composeProps(${entry.name}::class, listOf(`,
|
|
10360
|
+
...entry.states.map(
|
|
10361
|
+
(state) => ` dev.peach.expo.PeachExpoCompose.prop(${literal(state)}) { props: ${entry.name} -> props.${state} },`
|
|
10362
|
+
),
|
|
10363
|
+
" ))"
|
|
10364
|
+
].join("\n")
|
|
10365
|
+
)
|
|
10366
|
+
];
|
|
10367
|
+
if (edits.length > 0 || views.length > 0) {
|
|
10368
|
+
let text3 = import_node_fs16.default.readFileSync(file.file, "utf8").replaceAll("\r\n", "\n");
|
|
10369
|
+
for (const { range: range2, owner, field } of edits.sort((a, b) => b.range[0] - a.range[0]))
|
|
10370
|
+
text3 = `${text3.slice(0, range2[0])}dev.peach.expo.PeachExpoTypes.initial(${owner}::class, ${literal(field.key)}, ${field.required}) { ${text3.slice(range2[0], range2[1])} }${text3.slice(range2[1])}`;
|
|
10371
|
+
if (views.length > 0) {
|
|
10372
|
+
text3 = [
|
|
10373
|
+
text3,
|
|
10374
|
+
"",
|
|
10375
|
+
`internal fun peachExpoViews${index}() {`,
|
|
10376
|
+
...views,
|
|
10377
|
+
"}",
|
|
10378
|
+
""
|
|
10379
|
+
].join("\n");
|
|
10380
|
+
registrations.push(
|
|
10381
|
+
`${file.package ? `${file.package}.` : ""}peachExpoViews${index}()`
|
|
10382
|
+
);
|
|
10383
|
+
}
|
|
10384
|
+
const name2 = `PeachExpoSource_${index}_${import_node_path17.default.basename(file.file)}`;
|
|
10385
|
+
generated[name2] = text3;
|
|
10386
|
+
origins[name2] = file.file;
|
|
10387
|
+
}
|
|
10388
|
+
if (calls.length === 0) return;
|
|
10389
|
+
generated[`PeachExpoTypes_${index}.kt`] = [
|
|
10390
|
+
...file.package ? [`package ${file.package}`, ""] : [],
|
|
10391
|
+
`internal fun peachExpoTypes${index}() {`,
|
|
10392
|
+
...calls,
|
|
10393
|
+
"}",
|
|
10394
|
+
""
|
|
10395
|
+
].join("\n");
|
|
10396
|
+
registrations.push(
|
|
10397
|
+
`${file.package ? `${file.package}.` : ""}peachExpoTypes${index}()`
|
|
10398
|
+
);
|
|
10399
|
+
});
|
|
10400
|
+
return { generated, origins, registrations };
|
|
10401
|
+
}
|
|
10402
|
+
async function expoKotlinArtifact(root, moduleRoot, origin, modules) {
|
|
10403
|
+
const toolchain = readToolchain(moduleRoot);
|
|
10404
|
+
const language = appKotlinLanguage(root);
|
|
10405
|
+
const scanned = await scanExpoTypes(
|
|
10406
|
+
toolchain,
|
|
10407
|
+
import_node_path17.default.join(moduleRoot, "tools/expo-types.main.kts"),
|
|
10408
|
+
modules.sources
|
|
10409
|
+
);
|
|
10410
|
+
const usesCompose = scanned.some((file) => file.views.length > 0) || modules.sources.some(
|
|
10411
|
+
(file) => /\bandroidx\.compose\./.test(import_node_fs16.default.readFileSync(file, "utf8"))
|
|
10412
|
+
);
|
|
10413
|
+
const shims = [
|
|
10414
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "Sources"), /* @__PURE__ */ new Set()).filter(
|
|
10415
|
+
(file) => usesCompose || !file.endsWith("/OneNativeSourceViewDispatch.kt")
|
|
10416
|
+
),
|
|
10417
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "ExpoSources"), /* @__PURE__ */ new Set()),
|
|
10418
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "AndroidViewSources"), /* @__PURE__ */ new Set()),
|
|
10419
|
+
...usesCompose ? [
|
|
10420
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "ComposeSources")),
|
|
10421
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "ExpoComposeSources"), /* @__PURE__ */ new Set())
|
|
10422
|
+
] : []
|
|
10423
|
+
];
|
|
10424
|
+
const types = expoTypeSources(scanned);
|
|
10425
|
+
const rewritten = new Set(Object.values(types.origins));
|
|
10426
|
+
const entry = [
|
|
10427
|
+
"@file:OptIn(kotlin.js.ExperimentalJsExport::class)",
|
|
10428
|
+
"",
|
|
10429
|
+
"import dev.peach.expo.PeachExpoRuntime",
|
|
10430
|
+
"",
|
|
10431
|
+
"private val registered by lazy {",
|
|
10432
|
+
...types.registrations.map((call) => ` ${call}`),
|
|
10433
|
+
" PeachExpoRuntime.register(listOf(",
|
|
10434
|
+
...modules.modules.map(
|
|
10435
|
+
({ classifier, name: name2 }) => ` { ${classifier}() } to ${name2 === null ? "null" : JSON.stringify(name2)},`
|
|
10436
|
+
),
|
|
10437
|
+
" ))",
|
|
10438
|
+
"}",
|
|
10439
|
+
"",
|
|
10440
|
+
"@JsExport fun peachExpoListen(notify: () -> Unit) {",
|
|
10441
|
+
" registered",
|
|
10442
|
+
" PeachExpoRuntime.listen(notify)",
|
|
10443
|
+
"}",
|
|
10444
|
+
"",
|
|
10445
|
+
"@JsExport fun peachExpoCall(payload: String): String {",
|
|
10446
|
+
" registered",
|
|
10447
|
+
" return PeachExpoRuntime.dispatch(payload)",
|
|
10448
|
+
"}",
|
|
10449
|
+
""
|
|
10450
|
+
].join("\n");
|
|
10451
|
+
const artifact = await compileKotlin(
|
|
10452
|
+
{
|
|
10453
|
+
root,
|
|
10454
|
+
toolchain,
|
|
10455
|
+
language,
|
|
10456
|
+
sources: modules.sources.filter((file) => !rewritten.has(file)),
|
|
10457
|
+
generated: {
|
|
10458
|
+
...types.generated,
|
|
10459
|
+
"PeachExpoEntry.kt": entry,
|
|
10460
|
+
...usesCompose ? { "PeachViews.kt": viewsSource([]) } : {}
|
|
10461
|
+
},
|
|
10462
|
+
origins: types.origins,
|
|
10463
|
+
shims,
|
|
10464
|
+
usesCompose
|
|
10465
|
+
},
|
|
10466
|
+
origin
|
|
10467
|
+
);
|
|
10468
|
+
return { ...artifact, compose: usesCompose };
|
|
10469
|
+
}
|
|
10470
|
+
function viewsSource(viewIds) {
|
|
10471
|
+
return [
|
|
10472
|
+
"import dev.onejs.one.OneNativeSourceViewDispatch",
|
|
10473
|
+
"",
|
|
10474
|
+
"fun peachViewDispatcher(source: String): OneNativeSourceViewDispatch = when (source) {",
|
|
10475
|
+
...viewIds.map((id) => ` ${JSON.stringify(id)} -> OneNativeSourceViews_${id}()`),
|
|
10476
|
+
' else -> error("composable source $source is not linked; rebuild the app")',
|
|
10477
|
+
"}"
|
|
10478
|
+
].join("\n");
|
|
10479
|
+
}
|
|
10480
|
+
function viewModelInitializer({ name: name2, signature }) {
|
|
10481
|
+
const call = (args) => ` addInitializer(${name2}::class) { ${name2}(${args}) }`;
|
|
10482
|
+
switch (signature) {
|
|
10483
|
+
case "none":
|
|
10484
|
+
return call("");
|
|
10485
|
+
case "handle":
|
|
10486
|
+
return call("createSavedStateHandle()");
|
|
10487
|
+
case "application":
|
|
10488
|
+
return call("dev.peach.app.peachApplication()");
|
|
10489
|
+
case "application-handle":
|
|
10490
|
+
return call("dev.peach.app.peachApplication(), createSavedStateHandle()");
|
|
10491
|
+
case "misordered":
|
|
10492
|
+
return ` addInitializer(${name2}::class) { throw UnsupportedOperationException(${JSON.stringify(
|
|
10493
|
+
`Class ${name2.split(".").pop()} must have parameters in the proper order: [class android.app.Application, class androidx.lifecycle.SavedStateHandle]`
|
|
10494
|
+
)}) }`;
|
|
10495
|
+
}
|
|
10496
|
+
}
|
|
10497
|
+
function windowTheme(window) {
|
|
10498
|
+
return [
|
|
10499
|
+
" android.view.WindowTheme(",
|
|
10500
|
+
` ${window.edgeToEdgeEnforced}, ${argb(window.statusBarColor)}, ${argb(window.navigationBarColor)},`,
|
|
10501
|
+
` ${window.statusBarContrastEnforced}, ${window.navigationBarContrastEnforced},`,
|
|
10502
|
+
` ${window.lightStatusBar}, ${window.lightNavigationBar},`,
|
|
10503
|
+
" ),"
|
|
10504
|
+
];
|
|
10505
|
+
}
|
|
10506
|
+
async function kotlinAppArtifact(app, moduleRoot, origin) {
|
|
10507
|
+
const toolchain = readToolchain(moduleRoot);
|
|
10508
|
+
const appEntry = (viewModels) => [
|
|
10509
|
+
"@file:OptIn(kotlin.js.ExperimentalJsExport::class)",
|
|
10510
|
+
"",
|
|
10511
|
+
"import androidx.lifecycle.createSavedStateHandle",
|
|
10512
|
+
"",
|
|
10513
|
+
"@JsExport",
|
|
10514
|
+
"fun peachAppMount(density: Float, fontScale: Float, locale: String,",
|
|
10515
|
+
" font: String, insets: String, night: Boolean,",
|
|
10516
|
+
" invalidate: (Boolean) -> Unit): String = dev.peach.app.peachStartApp(",
|
|
10517
|
+
" dev.peach.app.PeachAppSpec(",
|
|
10518
|
+
` android.content.ComponentName(${literal(app.packageName)}, ${literal(app.launcher.name)}),`,
|
|
10519
|
+
` android.content.ComponentName(${literal(app.packageName)}, ${literal(app.launcher.targetClass)}),`,
|
|
10520
|
+
...windowTheme(app.window.day),
|
|
10521
|
+
...windowTheme(app.window.night),
|
|
10522
|
+
` { ${app.applicationClass ?? "android.app.Application"}() },`,
|
|
10523
|
+
` { ${app.launcher.targetClass}() },`,
|
|
10524
|
+
` ${app.handlesUiMode},`,
|
|
10525
|
+
` ${literal(app.softInputAdjust)},`,
|
|
10526
|
+
" androidx.lifecycle.viewmodel.viewModelFactory {",
|
|
10527
|
+
...viewModels.map(viewModelInitializer),
|
|
10528
|
+
" },",
|
|
10529
|
+
` ${app.predictiveBack},`,
|
|
10530
|
+
" ),",
|
|
10531
|
+
" density, fontScale, locale, font, insets, night, invalidate,",
|
|
10532
|
+
")",
|
|
10533
|
+
"",
|
|
10534
|
+
"@JsExport",
|
|
10535
|
+
`fun peachAppBack(): Boolean = dev.peach.app.peachAppBack(${app.predictiveBack})`,
|
|
10536
|
+
"",
|
|
10537
|
+
"@JsExport",
|
|
10538
|
+
"fun peachAppTask(foreground: Boolean) = dev.peach.app.peachAppTask(foreground)",
|
|
10539
|
+
"",
|
|
10540
|
+
"@JsExport",
|
|
10541
|
+
"fun peachAppNight(night: Boolean) = dev.peach.app.peachAppNight(night)",
|
|
10542
|
+
"",
|
|
10543
|
+
"@JsExport",
|
|
10544
|
+
"fun peachAppIme(bottom: Int, visible: Boolean) = dev.peach.app.peachAppIme(bottom, visible)",
|
|
10545
|
+
"",
|
|
10546
|
+
"@JsExport",
|
|
10547
|
+
"fun peachAppInsets(insets: String, visibleSystemBars: Int) = dev.peach.app.peachAppInsets(insets, visibleSystemBars)",
|
|
10548
|
+
""
|
|
10549
|
+
].join("\n");
|
|
10550
|
+
const generated = {
|
|
10551
|
+
"PeachEntry.kt": entrySource([]),
|
|
10552
|
+
"PeachViews.kt": viewsSource([]),
|
|
10553
|
+
"PeachAppEntry.kt": appEntry([]),
|
|
10554
|
+
...appResourceSources(app)
|
|
10555
|
+
};
|
|
10556
|
+
const shims = [
|
|
10557
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "Sources"), /* @__PURE__ */ new Set()),
|
|
10558
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "ComposeSources")),
|
|
10559
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "AppSources"), /* @__PURE__ */ new Set()),
|
|
10560
|
+
...kotlinSources(import_node_path17.default.join(moduleRoot, "AndroidViewSources"), /* @__PURE__ */ new Set())
|
|
10561
|
+
];
|
|
10562
|
+
return compileKotlin(
|
|
10563
|
+
{
|
|
10564
|
+
root: app.projectDir,
|
|
10565
|
+
toolchain,
|
|
10566
|
+
language: app.language,
|
|
10567
|
+
sources: app.sources,
|
|
10568
|
+
generated,
|
|
10569
|
+
shims,
|
|
10570
|
+
usesCompose: true,
|
|
10571
|
+
viewModels: {
|
|
10572
|
+
file: "PeachAppEntry.kt",
|
|
10573
|
+
render: appEntry,
|
|
10574
|
+
script: import_node_path17.default.join(moduleRoot, "tools/abi-classes.main.kts")
|
|
10575
|
+
}
|
|
10576
|
+
},
|
|
10577
|
+
origin
|
|
10578
|
+
);
|
|
10579
|
+
}
|
|
10580
|
+
function appResourceSources(app) {
|
|
10581
|
+
const field = (name2) => `\`${name2.replace(/[.-]/g, "_")}\``;
|
|
10582
|
+
const id = (type, entry) => `0x7f${type.toString(16).padStart(2, "0")}${entry.toString(16).padStart(4, "0")}`;
|
|
10583
|
+
const localized = (resources, render) => resources.map((resource) => ({
|
|
10584
|
+
name: resource.name,
|
|
10585
|
+
init: `mapOf(${Object.entries(resource.values).map(([locale, value]) => `${literal(locale)} to ${render(value)}`).join(", ")})`
|
|
10586
|
+
}));
|
|
10587
|
+
const kinds = [
|
|
10588
|
+
{
|
|
10589
|
+
type: "string",
|
|
10590
|
+
table: "peachAppStrings",
|
|
10591
|
+
value: "Map<String, String>",
|
|
10592
|
+
entries: localized(app.strings.strings, literal)
|
|
10593
|
+
},
|
|
10594
|
+
{
|
|
10595
|
+
type: "plurals",
|
|
10596
|
+
table: "peachAppPlurals",
|
|
10597
|
+
value: "Map<String, Map<String, String>>",
|
|
10598
|
+
entries: localized(
|
|
10599
|
+
app.strings.plurals,
|
|
10600
|
+
(items2) => `mapOf(${Object.entries(items2).map(([quantity, text3]) => `${literal(quantity)} to ${literal(text3 ?? "")}`).join(", ")})`
|
|
10601
|
+
)
|
|
10602
|
+
},
|
|
10603
|
+
{
|
|
10604
|
+
type: "array",
|
|
10605
|
+
table: "peachAppArrays",
|
|
10606
|
+
value: "Map<String, List<String>>",
|
|
10607
|
+
entries: localized(
|
|
10608
|
+
app.strings.arrays,
|
|
10609
|
+
(items2) => `listOf(${items2.map(literal).join(", ")})`
|
|
10610
|
+
)
|
|
10611
|
+
},
|
|
10612
|
+
{
|
|
10613
|
+
type: "drawable",
|
|
10614
|
+
table: "peachAppDrawables",
|
|
10615
|
+
value: "List<PeachDrawable>",
|
|
10616
|
+
entries: app.drawables.map((drawable) => ({
|
|
10617
|
+
name: drawable.name,
|
|
10618
|
+
init: `listOf(
|
|
10619
|
+
${drawable.files.map((file) => drawableInit(file, import_node_path17.default.relative(app.moduleDir, file.file))).join(",\n")}
|
|
10620
|
+
)`
|
|
10621
|
+
}))
|
|
10622
|
+
},
|
|
10623
|
+
// the day and the night ARGB
|
|
10624
|
+
{
|
|
10625
|
+
type: "color",
|
|
10626
|
+
table: "peachAppColors",
|
|
10627
|
+
value: "IntArray",
|
|
10628
|
+
entries: app.colors.map((color) => ({
|
|
10629
|
+
name: color.name,
|
|
10630
|
+
init: `intArrayOf(${argb(color.day)}, ${argb(color.night)})`
|
|
10631
|
+
}))
|
|
10632
|
+
}
|
|
10633
|
+
].map((kind, index) => ({
|
|
10634
|
+
...kind,
|
|
10635
|
+
entries: kind.entries.map((entry, number) => ({
|
|
10636
|
+
...entry,
|
|
10637
|
+
id: id(index + 1, number)
|
|
10638
|
+
}))
|
|
10639
|
+
}));
|
|
10640
|
+
return {
|
|
10641
|
+
"R.kt": [
|
|
10642
|
+
`package ${app.namespace}`,
|
|
10643
|
+
"",
|
|
10644
|
+
"object R {",
|
|
10645
|
+
...kinds.flatMap((kind) => [
|
|
10646
|
+
` object ${kind.type} {`,
|
|
10647
|
+
...kind.entries.map(
|
|
10648
|
+
(entry) => ` const val ${field(entry.name)}: Int = ${entry.id}`
|
|
10649
|
+
),
|
|
10650
|
+
" }"
|
|
10651
|
+
]),
|
|
10652
|
+
"}",
|
|
10653
|
+
""
|
|
10654
|
+
].join("\n"),
|
|
10655
|
+
"PeachAppResources.kt": [
|
|
10656
|
+
"package dev.peach.app",
|
|
10657
|
+
"",
|
|
10658
|
+
...[
|
|
10659
|
+
"androidx.compose.ui.graphics.BlendMode",
|
|
10660
|
+
"androidx.compose.ui.graphics.Color",
|
|
10661
|
+
"androidx.compose.ui.graphics.PathFillType",
|
|
10662
|
+
"androidx.compose.ui.graphics.StrokeCap",
|
|
10663
|
+
"androidx.compose.ui.graphics.StrokeJoin",
|
|
10664
|
+
"androidx.compose.ui.graphics.vector.ImageVector",
|
|
10665
|
+
"androidx.compose.ui.graphics.vector.addPathNodes",
|
|
10666
|
+
"androidx.compose.ui.unit.Dp"
|
|
10667
|
+
].map((name2) => `import ${name2}`),
|
|
10668
|
+
"",
|
|
10669
|
+
...kinds.flatMap((kind) => [
|
|
10670
|
+
`internal val ${kind.table}: Map<Int, ${kind.value}> = mapOf(`,
|
|
10671
|
+
...kind.entries.map((entry) => ` ${entry.id} to ${entry.init},`),
|
|
10672
|
+
")",
|
|
10673
|
+
""
|
|
10674
|
+
])
|
|
10675
|
+
].join("\n")
|
|
10676
|
+
};
|
|
10677
|
+
}
|
|
10678
|
+
function drawableInit(drawable, file) {
|
|
10679
|
+
const where = `${literal(file)}, ${drawable.density}, ${drawable.version}`;
|
|
10680
|
+
if (drawable.kind === "xml") return `PeachDrawable.Xml(${where})`;
|
|
10681
|
+
if (drawable.kind === "bitmap")
|
|
10682
|
+
return `PeachDrawable.Bitmap(${where}, ${drawable.ninePatch}, ${literal(
|
|
10683
|
+
import_node_fs16.default.readFileSync(drawable.file).toString("base64")
|
|
10684
|
+
)})`;
|
|
10685
|
+
const vector = drawable.vector;
|
|
10686
|
+
const float = (value) => `${value}f`;
|
|
10687
|
+
const pick = (value) => value.day === value.night ? argb(value.day) : `if (night) ${argb(value.night)} else ${argb(value.day)}`;
|
|
10688
|
+
const nodes = (pathData) => pathData ? `addPathNodes(${literal(pathData)})` : "emptyList()";
|
|
10689
|
+
const calls = vector.calls.map((call) => {
|
|
10690
|
+
if (call.call === "clear") return ".clearGroup()";
|
|
10691
|
+
if (call.call === "clip")
|
|
10692
|
+
return `.addGroup(name = ${literal(call.name)}, clipPathData = ${nodes(call.pathData)})`;
|
|
10693
|
+
if (call.call === "group")
|
|
10694
|
+
return `.addGroup(${[
|
|
10695
|
+
literal(call.name),
|
|
10696
|
+
...[
|
|
10697
|
+
call.rotate,
|
|
10698
|
+
call.pivotX,
|
|
10699
|
+
call.pivotY,
|
|
10700
|
+
call.scaleX,
|
|
10701
|
+
call.scaleY,
|
|
10702
|
+
call.translateX,
|
|
10703
|
+
call.translateY
|
|
10704
|
+
].map(float)
|
|
10705
|
+
].join(", ")})`;
|
|
10706
|
+
return `.addPath(${[
|
|
10707
|
+
nodes(call.pathData),
|
|
10708
|
+
`PathFillType.${call.fillType}`,
|
|
10709
|
+
literal(call.name),
|
|
10710
|
+
`peachBrush(${pick(call.fill)})`,
|
|
10711
|
+
float(call.fillAlpha),
|
|
10712
|
+
`peachBrush(${pick(call.stroke)})`,
|
|
10713
|
+
float(call.strokeAlpha),
|
|
10714
|
+
float(call.strokeWidth),
|
|
10715
|
+
`StrokeCap.${call.cap}`,
|
|
10716
|
+
`StrokeJoin.${call.join}`,
|
|
10717
|
+
...[call.miter, call.trimStart, call.trimEnd, call.trimOffset].map(float)
|
|
10718
|
+
].join(", ")})`;
|
|
10719
|
+
});
|
|
10720
|
+
return [
|
|
10721
|
+
`PeachDrawable.Vector(${where}) { night -> ImageVector.Builder(`,
|
|
10722
|
+
` defaultWidth = Dp(${float(vector.width)}), defaultHeight = Dp(${float(vector.height)}),`,
|
|
10723
|
+
` viewportWidth = ${float(vector.viewportWidth)}, viewportHeight = ${float(vector.viewportHeight)},`,
|
|
10724
|
+
` tintColor = ${vector.tint ? `Color(${pick(vector.tint)})` : "Color.Unspecified"},`,
|
|
10725
|
+
` tintBlendMode = BlendMode.${vector.tintMode}, autoMirror = ${vector.autoMirror},`,
|
|
10726
|
+
` )`,
|
|
10727
|
+
...calls.map((call) => ` ${call}`),
|
|
10728
|
+
" .build() }"
|
|
10729
|
+
].join("\n");
|
|
10730
|
+
}
|
|
10731
|
+
async function compileKotlin(input, origin) {
|
|
10732
|
+
const {
|
|
10733
|
+
root,
|
|
10734
|
+
toolchain,
|
|
10735
|
+
language,
|
|
10736
|
+
sources,
|
|
10737
|
+
generated,
|
|
10738
|
+
origins = {},
|
|
10739
|
+
shims,
|
|
10740
|
+
usesCompose,
|
|
10741
|
+
viewModels
|
|
10742
|
+
} = input;
|
|
10743
|
+
const digest2 = (0, import_node_crypto9.createHash)("sha256");
|
|
10744
|
+
digest2.update(JSON.stringify({ format: BUILD_FORMAT, toolchain, language }));
|
|
10745
|
+
for (const file of [...shims, ...sources, ...viewModels ? [viewModels.script] : []])
|
|
10746
|
+
digest2.update(`${import_node_path17.default.relative(root, file)}\0${import_node_fs16.default.readFileSync(file, "utf8")}\0`);
|
|
10747
|
+
for (const [name2, text3] of Object.entries(generated))
|
|
10748
|
+
digest2.update(`${name2}\0${text3}\0`);
|
|
10749
|
+
const hash = digest2.digest("hex").slice(0, 24);
|
|
10750
|
+
const artifact = {
|
|
10751
|
+
url: `${origin}${KOTLIN_ARTIFACT_PREFIX}${hash}/app.mjs`,
|
|
10752
|
+
hash
|
|
10753
|
+
};
|
|
10754
|
+
const out = import_node_path17.default.join(buildsDir(), hash);
|
|
10755
|
+
if (import_node_fs16.default.existsSync(import_node_path17.default.join(out, "js", "app.wasm"))) return artifact;
|
|
10756
|
+
const pending = builds.get(hash);
|
|
10757
|
+
if (pending) return pending;
|
|
10758
|
+
const build = (async () => {
|
|
10759
|
+
const ready = await ensureToolchain(toolchain);
|
|
10760
|
+
const { kotlinc } = ready;
|
|
10761
|
+
const libraries = [...ready.libraries];
|
|
10762
|
+
const composeRuntime = import_node_path17.default.join(
|
|
10763
|
+
kotlinHome(),
|
|
10764
|
+
toolchain.compiler.version,
|
|
10765
|
+
toolchain.composeRuntime.name
|
|
10766
|
+
);
|
|
10767
|
+
if (usesCompose) {
|
|
10768
|
+
for (const library of toolchain.composeLibraries) {
|
|
10769
|
+
const target = import_node_path17.default.join(kotlinHome(), toolchain.compiler.version, library.name);
|
|
10770
|
+
await fetchVerified(library, target);
|
|
10771
|
+
libraries.push(target);
|
|
10772
|
+
}
|
|
10773
|
+
await fetchVerified(toolchain.composeRuntime, composeRuntime);
|
|
10774
|
+
}
|
|
10775
|
+
import_node_fs16.default.mkdirSync(buildsDir(), { recursive: true });
|
|
10776
|
+
const work = import_node_fs16.default.mkdtempSync(import_node_path17.default.join(buildsDir(), `${hash}-`));
|
|
10777
|
+
const generatedDir = import_node_path17.default.join(work, "generated");
|
|
10778
|
+
import_node_fs16.default.mkdirSync(generatedDir);
|
|
10779
|
+
for (const [name2, text3] of Object.entries(generated))
|
|
10780
|
+
import_node_fs16.default.writeFileSync(import_node_path17.default.join(generatedDir, name2), text3);
|
|
10781
|
+
const common = [
|
|
10782
|
+
// the full upstream Compose graph exceeds kotlinc's 512 mib default heap.
|
|
10783
|
+
"-J-Xmx2g",
|
|
10784
|
+
"-Xallow-kotlin-package",
|
|
10785
|
+
"-Xwasm-target=js",
|
|
10786
|
+
"-libraries",
|
|
10787
|
+
libraries.join(import_node_path17.default.delimiter)
|
|
10788
|
+
];
|
|
10789
|
+
const compileKlib = (outputDir) => run4(
|
|
10790
|
+
kotlinc,
|
|
10791
|
+
[
|
|
10792
|
+
...common,
|
|
10793
|
+
...usesCompose ? [
|
|
10794
|
+
`-Xplugin=${import_node_path17.default.resolve(import_node_path17.default.dirname(kotlinc), "../lib/compose-compiler-plugin.jar")}`
|
|
10795
|
+
] : [],
|
|
10796
|
+
"-language-version",
|
|
10797
|
+
language,
|
|
10798
|
+
"-api-version",
|
|
10799
|
+
language,
|
|
10800
|
+
"-nowarn",
|
|
10801
|
+
"-nopack",
|
|
10802
|
+
"-ir-output-dir",
|
|
10803
|
+
outputDir,
|
|
10804
|
+
"-ir-output-name",
|
|
10805
|
+
"app",
|
|
10806
|
+
...shims,
|
|
10807
|
+
...sources,
|
|
10808
|
+
...Object.keys(generated).map((name2) => import_node_path17.default.join(generatedDir, name2))
|
|
10809
|
+
],
|
|
10810
|
+
{ maxBuffer: 16 * 1024 * 1024 }
|
|
10811
|
+
);
|
|
10812
|
+
try {
|
|
10813
|
+
if (viewModels && sources.some((file) => import_node_fs16.default.readFileSync(file, "utf8").includes("ViewModel"))) {
|
|
10814
|
+
await compileKlib(import_node_path17.default.join(work, "abi"));
|
|
10815
|
+
const { stdout } = await run4(
|
|
10816
|
+
import_node_path17.default.join(import_node_path17.default.dirname(kotlinc), "kotlinc"),
|
|
10817
|
+
[
|
|
10818
|
+
"-cp",
|
|
10819
|
+
import_node_path17.default.resolve(import_node_path17.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
|
|
10820
|
+
"-script",
|
|
10821
|
+
viewModels.script,
|
|
10822
|
+
import_node_path17.default.join(work, "abi")
|
|
10823
|
+
],
|
|
10824
|
+
{ maxBuffer: 64 * 1024 * 1024 }
|
|
10825
|
+
);
|
|
10826
|
+
import_node_fs16.default.writeFileSync(
|
|
10827
|
+
import_node_path17.default.join(generatedDir, viewModels.file),
|
|
10828
|
+
viewModels.render(viewModelClasses(readAbiClasses(stdout)))
|
|
10829
|
+
);
|
|
10830
|
+
}
|
|
10831
|
+
await compileKlib(import_node_path17.default.join(work, "klib"));
|
|
10832
|
+
await run4(
|
|
10833
|
+
kotlinc,
|
|
10834
|
+
[
|
|
10835
|
+
...common,
|
|
10836
|
+
"-nowarn",
|
|
10837
|
+
`-Xinclude=${import_node_path17.default.join(work, "klib")}`,
|
|
10838
|
+
"-Xir-produce-js",
|
|
10839
|
+
"-ir-output-dir",
|
|
10840
|
+
import_node_path17.default.join(work, "js"),
|
|
10841
|
+
"-ir-output-name",
|
|
10842
|
+
"app"
|
|
10843
|
+
],
|
|
10844
|
+
{ maxBuffer: 16 * 1024 * 1024 }
|
|
10845
|
+
);
|
|
10846
|
+
if (usesCompose) {
|
|
10847
|
+
await run4("unzip", [
|
|
10848
|
+
"-q",
|
|
10849
|
+
"-j",
|
|
10850
|
+
composeRuntime,
|
|
10851
|
+
"skiko.mjs",
|
|
10852
|
+
"-d",
|
|
10853
|
+
import_node_path17.default.join(work, "js")
|
|
10854
|
+
]);
|
|
10855
|
+
const skikoPath = import_node_path17.default.join(work, "js", "skiko.mjs");
|
|
10856
|
+
const upstream = (0, import_acorn.parse)(import_node_fs16.default.readFileSync(skikoPath, "utf8"), {
|
|
10857
|
+
ecmaVersion: "latest",
|
|
10858
|
+
sourceType: "module"
|
|
10859
|
+
});
|
|
10860
|
+
const bindings = [];
|
|
10861
|
+
for (const statement of upstream.body) {
|
|
10862
|
+
if (statement.type !== "ExportNamedDeclaration" || statement.declaration?.type !== "VariableDeclaration" || statement.declaration.kind !== "let")
|
|
10863
|
+
continue;
|
|
10864
|
+
for (const binding of statement.declaration.declarations) {
|
|
10865
|
+
if (binding.id.type !== "Identifier")
|
|
10866
|
+
throw new Error("Skiko binding must have one exported identifier");
|
|
10867
|
+
bindings.push(binding.id.name);
|
|
10868
|
+
}
|
|
10869
|
+
}
|
|
10870
|
+
if (bindings.length !== 967) throw new Error("pinned Skiko binding count changed");
|
|
10871
|
+
const names = [
|
|
10872
|
+
"awaitSkiko",
|
|
10873
|
+
"loadedWasm",
|
|
10874
|
+
"registerSkikoWasmReadyCallback",
|
|
10875
|
+
"skikoApi",
|
|
10876
|
+
"GL",
|
|
10877
|
+
...bindings
|
|
10878
|
+
];
|
|
10879
|
+
import_node_fs16.default.writeFileSync(
|
|
10880
|
+
skikoPath,
|
|
10881
|
+
[
|
|
10882
|
+
"const runtime = globalThis.__peachKotlinSkiko;",
|
|
10883
|
+
"if (!runtime) throw Error('Kotlin tenant runtime was not installed before guest evaluation');",
|
|
10884
|
+
`for (const name of ${JSON.stringify(names)}) if (!(name in runtime)) throw Error('Kotlin tenant runtime has no ' + name);`,
|
|
10885
|
+
...names.map((name2) => `export const ${name2} = runtime.${name2};`),
|
|
10886
|
+
""
|
|
10887
|
+
].join("\n")
|
|
10888
|
+
);
|
|
10889
|
+
}
|
|
10890
|
+
if (usesCompose) {
|
|
10891
|
+
for (const library of toolchain.composeJsLibraries) {
|
|
10892
|
+
let imported = false;
|
|
10893
|
+
for (const file of import_node_fs16.default.readdirSync(import_node_path17.default.join(work, "js"))) {
|
|
10894
|
+
if (!file.endsWith(".mjs")) continue;
|
|
10895
|
+
const target = import_node_path17.default.join(work, "js", file);
|
|
10896
|
+
const source = import_node_fs16.default.readFileSync(target, "utf8");
|
|
10897
|
+
let next = source;
|
|
10898
|
+
for (const quote of ["'", '"'])
|
|
10899
|
+
next = next.replaceAll(
|
|
10900
|
+
`from ${quote}${library.module}${quote}`,
|
|
10901
|
+
`from ${quote}./${library.file}${quote}`
|
|
10902
|
+
);
|
|
10903
|
+
if (next === source) continue;
|
|
10904
|
+
import_node_fs16.default.writeFileSync(target, next);
|
|
10905
|
+
imported = true;
|
|
10906
|
+
}
|
|
10907
|
+
if (!imported) continue;
|
|
10908
|
+
const archive = import_node_path17.default.join(
|
|
10909
|
+
kotlinHome(),
|
|
10910
|
+
toolchain.compiler.version,
|
|
10911
|
+
library.name
|
|
10912
|
+
);
|
|
10913
|
+
await fetchVerified(library, archive);
|
|
10914
|
+
const { stdout } = await run4("tar", ["-xOf", archive, library.archiveEntry], {
|
|
10915
|
+
maxBuffer: 16 * 1024 * 1024
|
|
10916
|
+
});
|
|
10917
|
+
import_node_fs16.default.writeFileSync(import_node_path17.default.join(work, "js", library.file), stdout);
|
|
10918
|
+
}
|
|
10919
|
+
}
|
|
10920
|
+
} catch (error) {
|
|
10921
|
+
import_node_fs16.default.rmSync(work, { recursive: true, force: true });
|
|
10922
|
+
let output = isRecord(error) ? `${String(error.stderr ?? "")}${String(error.stdout ?? "")}` : "";
|
|
10923
|
+
for (const [name2, source] of Object.entries(origins))
|
|
10924
|
+
output = output.replaceAll(import_node_path17.default.join(generatedDir, name2), source);
|
|
10925
|
+
throw new Error(
|
|
10926
|
+
`kotlin compile failed:
|
|
10927
|
+
${output.trim() || (error instanceof Error ? error.message : String(error))}`
|
|
10928
|
+
);
|
|
10929
|
+
}
|
|
10930
|
+
const seams = [
|
|
10931
|
+
["process.release.name", "process.release?.name"]
|
|
10932
|
+
];
|
|
10933
|
+
const js = import_node_fs16.default.readdirSync(import_node_path17.default.join(work, "js")).filter((file) => file.endsWith(".mjs"));
|
|
10934
|
+
if (js.some(
|
|
10935
|
+
(file) => import_node_fs16.default.readFileSync(import_node_path17.default.join(work, "js", file), "utf8").includes("'kotlinx.coroutines.")
|
|
10936
|
+
))
|
|
10937
|
+
seams.push([
|
|
10938
|
+
"(typeof(window) !== 'undefined' && window != null && typeof(window.addEventListener) === 'function') ? window : null",
|
|
10939
|
+
"null"
|
|
10940
|
+
]);
|
|
10941
|
+
for (const [from, to] of seams) {
|
|
10942
|
+
let patched = 0;
|
|
10943
|
+
for (const file of js) {
|
|
10944
|
+
const target = import_node_path17.default.join(work, "js", file);
|
|
10945
|
+
const text3 = import_node_fs16.default.readFileSync(target, "utf8");
|
|
10946
|
+
const next = text3.replaceAll(from, to);
|
|
10947
|
+
if (next !== text3) {
|
|
10948
|
+
patched++;
|
|
10949
|
+
import_node_fs16.default.writeFileSync(target, next);
|
|
10950
|
+
}
|
|
10951
|
+
}
|
|
10952
|
+
if (patched === 0)
|
|
10953
|
+
throw new Error(
|
|
10954
|
+
`kotlin output no longer contains ${from}; recheck how it detects its host in Peach`
|
|
10955
|
+
);
|
|
10956
|
+
}
|
|
10957
|
+
try {
|
|
10958
|
+
import_node_fs16.default.renameSync(work, out);
|
|
10959
|
+
} catch (error) {
|
|
10960
|
+
if (!import_node_fs16.default.existsSync(import_node_path17.default.join(out, "js", "app.wasm"))) throw error;
|
|
10961
|
+
import_node_fs16.default.rmSync(work, { recursive: true, force: true });
|
|
10962
|
+
}
|
|
10963
|
+
return artifact;
|
|
10964
|
+
})().finally(() => builds.delete(hash));
|
|
10965
|
+
builds.set(hash, build);
|
|
10966
|
+
return build;
|
|
10967
|
+
}
|
|
10968
|
+
function kotlinArtifactFiles(hash) {
|
|
10969
|
+
const dir = import_node_path17.default.join(buildsDir(), hash, "js");
|
|
10970
|
+
return import_node_fs16.default.readdirSync(dir).sort().map((name2) => {
|
|
10971
|
+
const contentType = CONTENT_TYPES[import_node_path17.default.extname(name2)];
|
|
10972
|
+
if (!contentType) throw new Error(`unexpected kotlin artifact file ${name2}`);
|
|
10973
|
+
return { name: name2, bytes: import_node_fs16.default.readFileSync(import_node_path17.default.join(dir, name2)), contentType };
|
|
10974
|
+
});
|
|
10975
|
+
}
|
|
10976
|
+
function serveKotlinArtifact(pathname, res) {
|
|
10977
|
+
if (!pathname.startsWith(KOTLIN_ARTIFACT_PREFIX)) return false;
|
|
10978
|
+
const [hash, file, ...rest] = pathname.slice(KOTLIN_ARTIFACT_PREFIX.length).split("/");
|
|
10979
|
+
const type = file ? CONTENT_TYPES[import_node_path17.default.extname(file)] : void 0;
|
|
10980
|
+
if (!hash || !/^[0-9a-f]+$/.test(hash) || !file || rest.length > 0 || !type || file.includes("..")) {
|
|
10981
|
+
res.statusCode = 404;
|
|
10982
|
+
res.end("not a kotlin artifact");
|
|
10983
|
+
return true;
|
|
10984
|
+
}
|
|
10985
|
+
const target = import_node_path17.default.join(buildsDir(), hash, "js", file);
|
|
10986
|
+
if (!import_node_fs16.default.existsSync(target)) {
|
|
10987
|
+
res.statusCode = 404;
|
|
10988
|
+
res.end(`kotlin artifact ${hash}/${file} was not built`);
|
|
10989
|
+
return true;
|
|
10990
|
+
}
|
|
10991
|
+
res.setHeader("access-control-allow-origin", "*");
|
|
10992
|
+
res.setHeader("content-type", type);
|
|
10993
|
+
res.setHeader("cache-control", "public, max-age=31536000, immutable");
|
|
10994
|
+
res.end(import_node_fs16.default.readFileSync(target));
|
|
10995
|
+
return true;
|
|
10996
|
+
}
|
|
10997
|
+
function peachKotlinModuleRoot() {
|
|
10998
|
+
return import_node_path17.default.resolve(import_node_path17.default.dirname((0, import_node_url2.fileURLToPath)(__sootsim_import_meta_url)), "..", "kotlin");
|
|
10999
|
+
}
|
|
11000
|
+
async function serveKotlinRequest(pathname, res, app) {
|
|
11001
|
+
if (serveKotlinArtifact(pathname, res)) return true;
|
|
11002
|
+
if (pathname !== KOTLIN_PACKAGE_PATH) return false;
|
|
11003
|
+
res.setHeader("access-control-allow-origin", "*");
|
|
11004
|
+
try {
|
|
11005
|
+
const artifact = app.project ? await kotlinAppArtifact(app.project, app.moduleRoot, app.origin) : await kotlinArtifact(app.root, app.moduleRoot, app.origin);
|
|
11006
|
+
res.setHeader("content-type", "application/json");
|
|
11007
|
+
res.end(JSON.stringify({ ...artifact, hmrPath: app.hmrPath }));
|
|
11008
|
+
} catch (error) {
|
|
11009
|
+
res.statusCode = 500;
|
|
11010
|
+
res.end(error instanceof Error ? error.message : String(error));
|
|
11011
|
+
}
|
|
11012
|
+
return true;
|
|
11013
|
+
}
|
|
11014
|
+
var import_node_child_process10, import_node_crypto9, import_node_fs16, import_node_module2, import_node_path17, import_node_url2, import_node_util4, import_acorn, run4, KOTLIN_ARTIFACT_PREFIX, toolchainReady, SKIP_DIRS, BUILD_FORMAT, builds, expoTypeScans, argb, escapes, literal, CONTENT_TYPES, KOTLIN_PACKAGE_PATH;
|
|
11015
|
+
var init_kotlin_host = __esm({
|
|
11016
|
+
"src/kotlin-host.ts"() {
|
|
11017
|
+
"use strict";
|
|
11018
|
+
import_node_child_process10 = require("node:child_process");
|
|
11019
|
+
import_node_crypto9 = require("node:crypto");
|
|
11020
|
+
import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
11021
|
+
import_node_module2 = require("node:module");
|
|
11022
|
+
import_node_path17 = __toESM(require("node:path"), 1);
|
|
11023
|
+
import_node_url2 = require("node:url");
|
|
11024
|
+
import_node_util4 = require("node:util");
|
|
11025
|
+
import_acorn = require("acorn");
|
|
11026
|
+
init_home_paths();
|
|
11027
|
+
init_is_record();
|
|
11028
|
+
init_kotlin_view_models();
|
|
11029
|
+
run4 = (0, import_node_util4.promisify)(import_node_child_process10.execFile);
|
|
11030
|
+
KOTLIN_ARTIFACT_PREFIX = "/__peach/kotlin-artifact/";
|
|
11031
|
+
SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
11032
|
+
"node_modules",
|
|
11033
|
+
"ios",
|
|
11034
|
+
"android",
|
|
11035
|
+
"dist",
|
|
11036
|
+
"types",
|
|
11037
|
+
"build",
|
|
11038
|
+
"tests",
|
|
11039
|
+
"__tests__",
|
|
11040
|
+
"scripts"
|
|
11041
|
+
]);
|
|
11042
|
+
BUILD_FORMAT = 14;
|
|
11043
|
+
builds = /* @__PURE__ */ new Map();
|
|
11044
|
+
expoTypeScans = /* @__PURE__ */ new Map();
|
|
11045
|
+
argb = (color) => `0x${color.toString(16).padStart(8, "0").toUpperCase()}.toInt()`;
|
|
11046
|
+
escapes = {
|
|
11047
|
+
"\\": "\\\\",
|
|
11048
|
+
'"': '\\"',
|
|
11049
|
+
$: "\\$",
|
|
11050
|
+
"\n": "\\n",
|
|
11051
|
+
"\r": "\\r",
|
|
11052
|
+
" ": "\\t"
|
|
11053
|
+
};
|
|
11054
|
+
literal = (value) => `"${value.replace(
|
|
11055
|
+
/[\\"$\u0000-\u001f]/g,
|
|
11056
|
+
(char) => escapes[char] ?? `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`
|
|
11057
|
+
)}"`;
|
|
11058
|
+
CONTENT_TYPES = {
|
|
11059
|
+
".mjs": "text/javascript",
|
|
11060
|
+
".wasm": "application/wasm"
|
|
11061
|
+
};
|
|
11062
|
+
KOTLIN_PACKAGE_PATH = "/__peach/kotlin-package";
|
|
11063
|
+
}
|
|
11064
|
+
});
|
|
11065
|
+
|
|
11066
|
+
// src/expo-kotlin-host.ts
|
|
11067
|
+
async function collectExpoKotlinModules(appRoot) {
|
|
11068
|
+
appRoot = import_node_fs17.default.realpathSync(appRoot);
|
|
11069
|
+
let autolinker;
|
|
11070
|
+
try {
|
|
11071
|
+
autolinker = (0, import_node_module3.createRequire)(import_node_path18.default.join(appRoot, "package.json")).resolve(
|
|
11072
|
+
"expo-modules-autolinking/package.json"
|
|
11073
|
+
);
|
|
11074
|
+
} catch (error) {
|
|
11075
|
+
if (isRecord(error) && error.code === "MODULE_NOT_FOUND") return null;
|
|
11076
|
+
throw error;
|
|
11077
|
+
}
|
|
11078
|
+
const { stdout } = await run5(
|
|
11079
|
+
process.execPath,
|
|
11080
|
+
[
|
|
11081
|
+
import_node_path18.default.join(import_node_path18.default.dirname(autolinker), "bin/expo-modules-autolinking.js"),
|
|
11082
|
+
"resolve",
|
|
11083
|
+
"--platform",
|
|
11084
|
+
"android",
|
|
11085
|
+
"--project-root",
|
|
11086
|
+
appRoot,
|
|
11087
|
+
"--json"
|
|
11088
|
+
],
|
|
11089
|
+
{ timeout: 3e4, maxBuffer: 8 * 1024 * 1024, env: scriptEnv2 }
|
|
11090
|
+
);
|
|
11091
|
+
const resolved = JSON.parse(stdout);
|
|
11092
|
+
if (!isRecord(resolved) || !Array.isArray(resolved.modules))
|
|
11093
|
+
throw new Error("invalid Expo Android resolution");
|
|
11094
|
+
const result = { modules: [], sources: [] };
|
|
11095
|
+
for (const entry of resolved.modules) {
|
|
11096
|
+
if (!isRecord(entry) || !Array.isArray(entry.projects))
|
|
11097
|
+
throw new Error("invalid Expo Android module entry");
|
|
11098
|
+
for (const project of entry.projects) {
|
|
11099
|
+
if (!isRecord(project) || typeof project.sourceDir !== "string" || !Array.isArray(project.modules))
|
|
11100
|
+
throw new Error("invalid Expo Android project");
|
|
11101
|
+
const sourceDir = import_node_fs17.default.realpathSync(project.sourceDir);
|
|
11102
|
+
if (sourceDir.split(import_node_path18.default.sep).includes("node_modules")) continue;
|
|
11103
|
+
if (project.modules.length === 0) continue;
|
|
11104
|
+
for (const module2 of project.modules) {
|
|
11105
|
+
if (!isRecord(module2) || typeof module2.classifier !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)+$/.test(
|
|
11106
|
+
module2.classifier
|
|
11107
|
+
) || module2.name !== null && typeof module2.name !== "string")
|
|
11108
|
+
throw new Error(`${sourceDir}: invalid Expo Android module descriptor`);
|
|
11109
|
+
result.modules.push({ classifier: module2.classifier, name: module2.name });
|
|
11110
|
+
}
|
|
11111
|
+
const walk2 = (dir) => {
|
|
11112
|
+
if (!import_node_fs17.default.existsSync(dir)) return;
|
|
11113
|
+
for (const child of import_node_fs17.default.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
11114
|
+
const file = import_node_path18.default.join(dir, child.name);
|
|
11115
|
+
if (child.isSymbolicLink())
|
|
11116
|
+
throw new Error(`Expo Kotlin source is a symlink: ${file}`);
|
|
11117
|
+
if (child.isDirectory()) walk2(file);
|
|
11118
|
+
else if (child.name.endsWith(".java"))
|
|
11119
|
+
throw new Error(`${file}: Java sources in Expo modules are not supported yet`);
|
|
11120
|
+
else if (child.name.endsWith(".kt")) result.sources.push(file);
|
|
11121
|
+
}
|
|
11122
|
+
};
|
|
11123
|
+
walk2(import_node_path18.default.join(sourceDir, "src", "main", "java"));
|
|
11124
|
+
walk2(import_node_path18.default.join(sourceDir, "src", "main", "kotlin"));
|
|
11125
|
+
}
|
|
11126
|
+
}
|
|
11127
|
+
return result.modules.length === 0 ? null : result;
|
|
11128
|
+
}
|
|
11129
|
+
async function compileExpoKotlinModules(root, origin) {
|
|
11130
|
+
const found = await collectExpoKotlinModules(root);
|
|
11131
|
+
if (!found) return null;
|
|
11132
|
+
const namespaces = found.modules.map(
|
|
11133
|
+
(module2) => module2.name ?? module2.classifier.split(".").pop()
|
|
11134
|
+
);
|
|
11135
|
+
const { expoKotlinArtifact: expoKotlinArtifact2 } = await Promise.resolve().then(() => (init_kotlin_host(), kotlin_host_exports));
|
|
11136
|
+
try {
|
|
11137
|
+
const artifact = await expoKotlinArtifact2(root, MODULE_ROOT, origin, found);
|
|
11138
|
+
return { namespaces, module: artifact, failures: [] };
|
|
11139
|
+
} catch (error) {
|
|
11140
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
11141
|
+
const errors = message.match(/^.+\.kt:\d+:\d+: error:.*$/gm);
|
|
11142
|
+
if (!errors) throw error;
|
|
11143
|
+
return {
|
|
11144
|
+
namespaces,
|
|
11145
|
+
module: null,
|
|
11146
|
+
failures: namespaces.map((namespace) => ({
|
|
11147
|
+
namespace,
|
|
11148
|
+
diagnostic: errors.join("\n")
|
|
11149
|
+
}))
|
|
11150
|
+
};
|
|
11151
|
+
}
|
|
11152
|
+
}
|
|
11153
|
+
var import_node_child_process11, import_node_fs17, import_node_module3, import_node_path18, import_node_util5, run5, scriptEnv2, MODULE_ROOT;
|
|
11154
|
+
var init_expo_kotlin_host = __esm({
|
|
11155
|
+
"src/expo-kotlin-host.ts"() {
|
|
11156
|
+
"use strict";
|
|
11157
|
+
import_node_child_process11 = require("node:child_process");
|
|
11158
|
+
import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
11159
|
+
import_node_module3 = require("node:module");
|
|
11160
|
+
import_node_path18 = __toESM(require("node:path"), 1);
|
|
11161
|
+
import_node_util5 = require("node:util");
|
|
11162
|
+
init_internal_child();
|
|
11163
|
+
init_backend_origin();
|
|
11164
|
+
init_is_record();
|
|
11165
|
+
run5 = (0, import_node_util5.promisify)(import_node_child_process11.execFile);
|
|
11166
|
+
scriptEnv2 = { ...process.env, [RNX_FORKED_SCRIPT_ENV]: "1" };
|
|
11167
|
+
MODULE_ROOT = import_node_path18.default.resolve(__sootsim_import_meta_dirname, "../kotlin");
|
|
11168
|
+
}
|
|
11169
|
+
});
|
|
11170
|
+
|
|
11171
|
+
// src/expo-kotlin-bundle.ts
|
|
11172
|
+
var expo_kotlin_bundle_exports = {};
|
|
11173
|
+
__export(expo_kotlin_bundle_exports, {
|
|
11174
|
+
buildExpoKotlinBundle: () => buildExpoKotlinBundle
|
|
11175
|
+
});
|
|
11176
|
+
async function buildExpoKotlinBundle(appRoot) {
|
|
11177
|
+
const metadata = await compileExpoKotlinModules(appRoot, "");
|
|
11178
|
+
if (!metadata) return null;
|
|
11179
|
+
const { module: module2 } = metadata;
|
|
11180
|
+
if (!module2) return { metadata, assets: [] };
|
|
11181
|
+
const { kotlinArtifactFiles: kotlinArtifactFiles2 } = await Promise.resolve().then(() => (init_kotlin_host(), kotlin_host_exports));
|
|
11182
|
+
const dir = `__peach/kotlin/${module2.hash}`;
|
|
11183
|
+
return {
|
|
11184
|
+
metadata: { ...metadata, module: { ...module2, url: `${dir}/app.mjs` } },
|
|
11185
|
+
assets: kotlinArtifactFiles2(module2.hash).map((file) => ({
|
|
11186
|
+
path: `${dir}/${file.name}`,
|
|
11187
|
+
bytes: file.bytes,
|
|
11188
|
+
contentType: file.contentType
|
|
11189
|
+
}))
|
|
11190
|
+
};
|
|
11191
|
+
}
|
|
11192
|
+
var init_expo_kotlin_bundle = __esm({
|
|
11193
|
+
"src/expo-kotlin-bundle.ts"() {
|
|
11194
|
+
"use strict";
|
|
11195
|
+
init_expo_kotlin_host();
|
|
11196
|
+
}
|
|
11197
|
+
});
|
|
11198
|
+
|
|
11199
|
+
// src/bundle-channel.mjs
|
|
11200
|
+
var bundle_channel_exports = {};
|
|
11201
|
+
__export(bundle_channel_exports, {
|
|
11202
|
+
prepareBundleChannel: () => prepareBundleChannel,
|
|
11203
|
+
publishBundleChannel: () => publishBundleChannel,
|
|
11204
|
+
snapshotDevServerBundles: () => snapshotDevServerBundles,
|
|
11205
|
+
snapshotOneDevBundle: () => snapshotOneDevBundle
|
|
11206
|
+
});
|
|
11207
|
+
module.exports = __toCommonJS(bundle_channel_exports);
|
|
11208
|
+
var import_node_crypto10 = require("node:crypto");
|
|
11209
|
+
var import_node_vm = require("node:vm");
|
|
11210
|
+
|
|
11211
|
+
// ../contrast/src/runtime/process-group.ts
|
|
11212
|
+
var import_node_child_process = require("node:child_process");
|
|
11213
|
+
|
|
11214
|
+
// ../contrast/src/sleep.ts
|
|
11215
|
+
function sleep(ms) {
|
|
11216
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
11217
|
+
}
|
|
11218
|
+
|
|
11219
|
+
// ../contrast/src/runtime/process-group.ts
|
|
11220
|
+
var GRACEFUL_TIMEOUT_MS = 3e3;
|
|
11221
|
+
var FORCED_EXIT_TIMEOUT_MS = 1e3;
|
|
11222
|
+
function signalProcessGroup(child, signal) {
|
|
11223
|
+
if (!child.pid) return;
|
|
11224
|
+
try {
|
|
11225
|
+
process.kill(-child.pid, signal);
|
|
11226
|
+
} catch {
|
|
11227
|
+
try {
|
|
11228
|
+
process.kill(child.pid, signal);
|
|
11229
|
+
} catch {
|
|
11230
|
+
}
|
|
11231
|
+
}
|
|
11232
|
+
}
|
|
11233
|
+
function runningPids(pids) {
|
|
11234
|
+
return pids.filter((pid) => {
|
|
11235
|
+
try {
|
|
11236
|
+
process.kill(pid, 0);
|
|
11237
|
+
return true;
|
|
11238
|
+
} catch (error) {
|
|
11239
|
+
return error instanceof Error && "code" in error && error.code === "EPERM";
|
|
11240
|
+
}
|
|
11241
|
+
});
|
|
11242
|
+
}
|
|
11243
|
+
function groupIsEmpty(pgid) {
|
|
11244
|
+
try {
|
|
11245
|
+
process.kill(-pgid, 0);
|
|
11246
|
+
} catch (error) {
|
|
11247
|
+
if (!(error instanceof Error && "code" in error && error.code === "EPERM"))
|
|
11248
|
+
return true;
|
|
11249
|
+
}
|
|
11250
|
+
const result = (0, import_node_child_process.spawnSync)("ps", ["-A", "-o", "pgid=,stat="], {
|
|
11251
|
+
encoding: "utf8",
|
|
11252
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
11253
|
+
});
|
|
11254
|
+
if (result.error || result.status !== 0) return false;
|
|
11255
|
+
return !result.stdout.split("\n").some((line) => {
|
|
11256
|
+
const [group, state] = line.trim().split(/\s+/);
|
|
11257
|
+
return Number(group) === pgid && state !== void 0 && !state.startsWith("Z");
|
|
11258
|
+
});
|
|
11259
|
+
}
|
|
11260
|
+
async function waitForExit(pids, pgid, timeoutMs) {
|
|
11261
|
+
const deadline = Date.now() + timeoutMs;
|
|
11262
|
+
const gone = () => runningPids(pids).length === 0 && groupIsEmpty(pgid);
|
|
11263
|
+
while (Date.now() < deadline) {
|
|
11264
|
+
if (gone()) return true;
|
|
11265
|
+
await sleep(50);
|
|
11266
|
+
}
|
|
11267
|
+
return gone();
|
|
11268
|
+
}
|
|
11269
|
+
async function terminateProcessGroup(child, signal = "SIGTERM", gracefulTimeoutMs = GRACEFUL_TIMEOUT_MS) {
|
|
11270
|
+
if (!child.pid) {
|
|
11271
|
+
try {
|
|
11272
|
+
child.kill(signal);
|
|
11273
|
+
} catch {
|
|
11274
|
+
}
|
|
11275
|
+
return;
|
|
11276
|
+
}
|
|
11277
|
+
signalProcessGroup(child, "SIGSTOP");
|
|
11278
|
+
const descendants = /* @__PURE__ */ new Set();
|
|
11279
|
+
let parents = [child.pid];
|
|
11280
|
+
let inspectionError = null;
|
|
11281
|
+
while (parents.length > 0) {
|
|
11282
|
+
const result = (0, import_node_child_process.spawnSync)("pgrep", ["-P", parents.join(",")], {
|
|
11283
|
+
encoding: "utf8",
|
|
11284
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
11285
|
+
});
|
|
11286
|
+
if (result.error || result.status !== 0 && result.status !== 1) {
|
|
11287
|
+
inspectionError = new Error(
|
|
11288
|
+
`could not inspect descendants of processes ${parents.join(",")}: ${result.error?.message || result.stderr.trim() || `pgrep exited ${result.status}`}`
|
|
11289
|
+
);
|
|
11290
|
+
break;
|
|
11291
|
+
}
|
|
11292
|
+
const next = [];
|
|
11293
|
+
for (const line of result.stdout.split("\n")) {
|
|
11294
|
+
const descendantPid = Number(line.trim());
|
|
11295
|
+
if (Number.isInteger(descendantPid) && descendantPid > 1 && !descendants.has(descendantPid)) {
|
|
11296
|
+
descendants.add(descendantPid);
|
|
11297
|
+
next.push(descendantPid);
|
|
11298
|
+
try {
|
|
11299
|
+
process.kill(descendantPid, "SIGSTOP");
|
|
11300
|
+
} catch {
|
|
11301
|
+
}
|
|
11302
|
+
}
|
|
11303
|
+
}
|
|
11304
|
+
parents = next;
|
|
11305
|
+
}
|
|
11306
|
+
const pids = [child.pid, ...descendants];
|
|
11307
|
+
const gracefulDeadline = Date.now() + gracefulTimeoutMs;
|
|
9077
11308
|
try {
|
|
9078
11309
|
process.kill(child.pid, signal);
|
|
9079
11310
|
} catch {
|
|
@@ -9130,65 +11361,124 @@ async function terminateProcessGroup(child, signal = "SIGTERM", gracefulTimeoutM
|
|
|
9130
11361
|
if (inspectionError) throw inspectionError;
|
|
9131
11362
|
}
|
|
9132
11363
|
|
|
9133
|
-
// src/
|
|
11364
|
+
// src/bundle-channel.mjs
|
|
11365
|
+
init_backend_origin();
|
|
11366
|
+
|
|
11367
|
+
// src/bundleGlobalFooter.ts
|
|
11368
|
+
function readBundleGlobalFooter(source, name2) {
|
|
11369
|
+
const prefix = `globalThis.${name2}=`;
|
|
11370
|
+
const start = source.lastIndexOf(`
|
|
11371
|
+
${prefix}`);
|
|
11372
|
+
if (start < 0) return null;
|
|
11373
|
+
const end = source.indexOf("\n", start + 1);
|
|
11374
|
+
const line = source.slice(start + 1, end < 0 ? void 0 : end);
|
|
11375
|
+
if (!line.endsWith(";")) throw new Error(`${name2} footer is truncated`);
|
|
11376
|
+
const value = JSON.parse(line.slice(prefix.length, -1));
|
|
11377
|
+
if (value === null) throw new Error(`${name2} footer has no metadata`);
|
|
11378
|
+
return value;
|
|
11379
|
+
}
|
|
11380
|
+
function insertBundleGlobalFooter(source, name2, value) {
|
|
11381
|
+
const prefix = `globalThis.${name2}=`;
|
|
11382
|
+
const start = source.lastIndexOf(`
|
|
11383
|
+
${prefix}`);
|
|
11384
|
+
if (start >= 0) {
|
|
11385
|
+
readBundleGlobalFooter(source, name2);
|
|
11386
|
+
const end = source.indexOf("\n", start + 1);
|
|
11387
|
+
source = source.slice(0, start) + (end < 0 ? "" : source.slice(end));
|
|
11388
|
+
}
|
|
11389
|
+
const json = JSON.stringify(value).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/<\//g, "<\\/");
|
|
11390
|
+
const footer = `
|
|
11391
|
+
${prefix}${json};`;
|
|
11392
|
+
const identity = source.lastIndexOf("\nglobalThis.__sootsimModulePaths=");
|
|
11393
|
+
return identity < 0 ? source + footer : source.slice(0, identity) + footer + source.slice(identity);
|
|
11394
|
+
}
|
|
11395
|
+
|
|
11396
|
+
// src/expoKotlinContract.ts
|
|
9134
11397
|
function record(value) {
|
|
9135
11398
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
9136
11399
|
}
|
|
11400
|
+
function readExpoKotlinMetadata(value) {
|
|
11401
|
+
const invalid = () => new Error("invalid Expo Kotlin compilation metadata");
|
|
11402
|
+
if (!record(value) || !Array.isArray(value.namespaces) || !Array.isArray(value.failures))
|
|
11403
|
+
throw invalid();
|
|
11404
|
+
const namespaces = [];
|
|
11405
|
+
for (const namespace of value.namespaces) {
|
|
11406
|
+
if (typeof namespace !== "string") throw invalid();
|
|
11407
|
+
namespaces.push(namespace);
|
|
11408
|
+
}
|
|
11409
|
+
const failures = [];
|
|
11410
|
+
for (const failure2 of value.failures) {
|
|
11411
|
+
if (!record(failure2) || typeof failure2.namespace !== "string" || typeof failure2.diagnostic !== "string")
|
|
11412
|
+
throw invalid();
|
|
11413
|
+
failures.push({ namespace: failure2.namespace, diagnostic: failure2.diagnostic });
|
|
11414
|
+
}
|
|
11415
|
+
const module2 = value.module;
|
|
11416
|
+
if (module2 === null) return { namespaces, module: null, failures };
|
|
11417
|
+
if (!record(module2) || typeof module2.url !== "string" || typeof module2.hash !== "string" || typeof module2.compose !== "boolean")
|
|
11418
|
+
throw invalid();
|
|
11419
|
+
return {
|
|
11420
|
+
namespaces,
|
|
11421
|
+
module: { url: module2.url, hash: module2.hash, compose: module2.compose },
|
|
11422
|
+
failures
|
|
11423
|
+
};
|
|
11424
|
+
}
|
|
11425
|
+
function insertExpoKotlinFooter(source, metadata) {
|
|
11426
|
+
return insertBundleGlobalFooter(
|
|
11427
|
+
source,
|
|
11428
|
+
"__peachExpoKotlin",
|
|
11429
|
+
readExpoKotlinMetadata(metadata)
|
|
11430
|
+
);
|
|
11431
|
+
}
|
|
11432
|
+
|
|
11433
|
+
// src/expoSwiftContract.ts
|
|
11434
|
+
function record2(value) {
|
|
11435
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11436
|
+
}
|
|
9137
11437
|
function strings(value) {
|
|
9138
11438
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
9139
11439
|
}
|
|
9140
11440
|
function isExpoSwiftCompilationResult(value) {
|
|
9141
|
-
if (!
|
|
11441
|
+
if (!record2(value) || !strings(value.namespaces) || !Array.isArray(value.modules) || value.modules.length > 1 || !Array.isArray(value.failures))
|
|
9142
11442
|
return false;
|
|
9143
11443
|
const remaining = new Set(value.namespaces);
|
|
9144
11444
|
if (remaining.size !== value.namespaces.length) return false;
|
|
9145
11445
|
for (const artifact of value.modules) {
|
|
9146
|
-
if (!
|
|
11446
|
+
if (!record2(artifact) || !strings(artifact.namespaces) || artifact.namespaces.length === 0 || !artifact.namespaces.every((namespace) => remaining.delete(namespace)) || typeof artifact.url !== "string" || typeof artifact.hash !== "string" || typeof artifact.icuUrl !== "string" || typeof artifact.rootId !== "string")
|
|
9147
11447
|
return false;
|
|
9148
11448
|
}
|
|
9149
11449
|
for (const failure2 of value.failures) {
|
|
9150
|
-
if (!
|
|
11450
|
+
if (!record2(failure2) || typeof failure2.namespace !== "string" || !remaining.delete(failure2.namespace) || typeof failure2.diagnostic !== "string")
|
|
9151
11451
|
return false;
|
|
9152
11452
|
}
|
|
9153
11453
|
return remaining.size === 0;
|
|
9154
11454
|
}
|
|
9155
|
-
var FOOTER_PREFIX = "globalThis.__peachExpoSwift=";
|
|
9156
11455
|
function readExpoSwiftMetadata(value) {
|
|
9157
11456
|
if (value === null || value === void 0) return null;
|
|
9158
11457
|
if (!isExpoSwiftCompilationResult(value))
|
|
9159
11458
|
throw new Error("invalid Expo Swift compilation metadata");
|
|
9160
11459
|
return value;
|
|
9161
11460
|
}
|
|
9162
|
-
function readExpoSwiftFooter(source) {
|
|
9163
|
-
const start = source.lastIndexOf(`
|
|
9164
|
-
${FOOTER_PREFIX}`);
|
|
9165
|
-
if (start < 0) return null;
|
|
9166
|
-
const end = source.indexOf("\n", start + 1);
|
|
9167
|
-
const line = source.slice(start + 1, end < 0 ? void 0 : end);
|
|
9168
|
-
if (!line.endsWith(";")) throw new Error("Expo Swift footer is truncated");
|
|
9169
|
-
const metadata = readExpoSwiftMetadata(JSON.parse(line.slice(FOOTER_PREFIX.length, -1)));
|
|
9170
|
-
if (!metadata) throw new Error("Expo Swift footer has no metadata");
|
|
9171
|
-
return metadata;
|
|
9172
|
-
}
|
|
9173
11461
|
function insertExpoSwiftFooter(source, metadata) {
|
|
9174
11462
|
readExpoSwiftMetadata(metadata);
|
|
9175
|
-
|
|
9176
|
-
${FOOTER_PREFIX}`);
|
|
9177
|
-
if (start >= 0) {
|
|
9178
|
-
readExpoSwiftFooter(source);
|
|
9179
|
-
const end = source.indexOf("\n", start + 1);
|
|
9180
|
-
source = source.slice(0, start) + (end < 0 ? "" : source.slice(end));
|
|
9181
|
-
}
|
|
9182
|
-
const json = JSON.stringify(metadata).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/<\//g, "<\\/");
|
|
9183
|
-
const footer = `
|
|
9184
|
-
${FOOTER_PREFIX}${json};`;
|
|
9185
|
-
const identity = source.lastIndexOf("\nglobalThis.__sootsimModulePaths=");
|
|
9186
|
-
return identity < 0 ? source + footer : source.slice(0, identity) + footer + source.slice(identity);
|
|
11463
|
+
return insertBundleGlobalFooter(source, "__peachExpoSwift", metadata);
|
|
9187
11464
|
}
|
|
9188
11465
|
|
|
9189
11466
|
// src/bundle-channel.mjs
|
|
9190
|
-
var digest = (bytes) => (0,
|
|
11467
|
+
var digest = (bytes) => (0, import_node_crypto10.createHash)("sha256").update(bytes).digest("hex");
|
|
9191
11468
|
var segment = /^[a-zA-Z0-9._-]+$/;
|
|
11469
|
+
function packagedAssetDirectory(location) {
|
|
11470
|
+
const parsed = new URL(location, "https://packaged.invalid");
|
|
11471
|
+
if (parsed.origin !== "https://packaged.invalid")
|
|
11472
|
+
throw new Error(`non-packaged asset location: ${location}`);
|
|
11473
|
+
const outside = parsed.searchParams.get("unstable_path");
|
|
11474
|
+
if (outside === null) return parsed.pathname.replace(/^\/+/, "");
|
|
11475
|
+
return `assets/${outside.replace(/^\.\//, "").replace(/\.\.\//g, "_")}`;
|
|
11476
|
+
}
|
|
11477
|
+
var channelKey = (platform) => platform === "ios" ? "peach/channels/prod" : `peach/channels/${platform}/prod`;
|
|
11478
|
+
var nativeAssetPath = {
|
|
11479
|
+
ios: /^__peach\/(swift|swift-icu)\/[a-f0-9]{64}(\.wasm)?$/,
|
|
11480
|
+
android: /^__peach\/kotlin\/[a-f0-9]+\/[A-Za-z0-9._-]+\.(mjs|wasm)$/
|
|
11481
|
+
};
|
|
9192
11482
|
function prepareBundleChannel({
|
|
9193
11483
|
prefix,
|
|
9194
11484
|
publicOrigin,
|
|
@@ -9196,15 +11486,16 @@ function prepareBundleChannel({
|
|
|
9196
11486
|
runtimeVersion,
|
|
9197
11487
|
name: name2,
|
|
9198
11488
|
icon,
|
|
9199
|
-
|
|
9200
|
-
assets: assets2,
|
|
9201
|
-
expoSwift = null
|
|
11489
|
+
platforms
|
|
9202
11490
|
}) {
|
|
9203
11491
|
if (!/^[a-f0-9]{40}$/.test(sourceSha) || !/^\d+$/.test(runtimeVersion)) {
|
|
9204
11492
|
throw new Error("invalid bundle channel source identity");
|
|
9205
11493
|
}
|
|
9206
11494
|
const origin = new URL(publicOrigin);
|
|
9207
|
-
if (
|
|
11495
|
+
if (
|
|
11496
|
+
// a loopback origin serves local release proofs
|
|
11497
|
+
!(origin.protocol === "https:" || origin.protocol === "http:" && isLoopbackHost(origin.hostname)) || origin.pathname !== "/" || origin.search || origin.hash || origin.username || origin.password
|
|
11498
|
+
) {
|
|
9208
11499
|
throw new Error("bundle channels require a public HTTPS origin");
|
|
9209
11500
|
}
|
|
9210
11501
|
if (!prefix.split("/").every((s) => segment.test(s) && s !== "." && s !== "..")) {
|
|
@@ -9212,6 +11503,39 @@ function prepareBundleChannel({
|
|
|
9212
11503
|
}
|
|
9213
11504
|
if (!icon.subarray(0, 8).equals(Buffer.from("89504e470d0a1a0a", "hex")))
|
|
9214
11505
|
throw new Error("bundle channel icon must be PNG");
|
|
11506
|
+
if (!platforms.length) throw new Error("bundle channel has no platforms");
|
|
11507
|
+
if (new Set(platforms.map((p) => p.platform)).size !== platforms.length)
|
|
11508
|
+
throw new Error("bundle channel repeats a platform");
|
|
11509
|
+
const channels = platforms.map(
|
|
11510
|
+
(snapshot) => prepareChannel({
|
|
11511
|
+
prefix,
|
|
11512
|
+
origin,
|
|
11513
|
+
sourceSha,
|
|
11514
|
+
runtimeVersion,
|
|
11515
|
+
name: name2,
|
|
11516
|
+
icon,
|
|
11517
|
+
...snapshot
|
|
11518
|
+
})
|
|
11519
|
+
);
|
|
11520
|
+
return { prefix, origin: origin.origin, channels };
|
|
11521
|
+
}
|
|
11522
|
+
function prepareChannel({
|
|
11523
|
+
prefix,
|
|
11524
|
+
origin,
|
|
11525
|
+
sourceSha,
|
|
11526
|
+
runtimeVersion,
|
|
11527
|
+
name: name2,
|
|
11528
|
+
icon,
|
|
11529
|
+
platform,
|
|
11530
|
+
bundle,
|
|
11531
|
+
assets: assets2,
|
|
11532
|
+
expoSwift = null,
|
|
11533
|
+
expoKotlin = null
|
|
11534
|
+
}) {
|
|
11535
|
+
if (!(platform in nativeAssetPath)) throw new Error(`unknown platform: ${platform}`);
|
|
11536
|
+
const native = platform === "ios" ? expoSwift : expoKotlin;
|
|
11537
|
+
if ((platform === "ios" ? expoKotlin : expoSwift) !== null)
|
|
11538
|
+
throw new Error(`${platform} bundle carries another platform's native modules`);
|
|
9215
11539
|
const files2 = /* @__PURE__ */ new Map();
|
|
9216
11540
|
for (const asset of assets2) {
|
|
9217
11541
|
if (!asset.path.startsWith("assets/") || !asset.path.split("/").every((s) => s && s !== "." && s !== ".." && !/[\\?#%]/.test(s))) {
|
|
@@ -9220,23 +11544,23 @@ function prepareBundleChannel({
|
|
|
9220
11544
|
if (files2.has(asset.path)) throw new Error(`duplicate packaged asset: ${asset.path}`);
|
|
9221
11545
|
files2.set(asset.path, asset.bytes);
|
|
9222
11546
|
}
|
|
9223
|
-
for (const asset of
|
|
9224
|
-
if (
|
|
9225
|
-
throw new Error(`invalid
|
|
11547
|
+
for (const asset of native?.assets ?? []) {
|
|
11548
|
+
if (!nativeAssetPath[platform].test(asset.path))
|
|
11549
|
+
throw new Error(`invalid native artifact path: ${asset.path}`);
|
|
9226
11550
|
if (files2.has(asset.path)) throw new Error(`duplicate packaged asset: ${asset.path}`);
|
|
9227
11551
|
files2.set(asset.path, asset.bytes);
|
|
9228
11552
|
}
|
|
9229
|
-
const identity = (0,
|
|
9230
|
-
for (const [
|
|
11553
|
+
const identity = (0, import_node_crypto10.createHash)("sha256").update(bundle).update(icon);
|
|
11554
|
+
for (const [path18, bytes] of [...files2].sort(
|
|
9231
11555
|
([a], [b]) => a < b ? -1 : a > b ? 1 : 0
|
|
9232
11556
|
)) {
|
|
9233
|
-
identity.update(JSON.stringify([
|
|
11557
|
+
identity.update(JSON.stringify([path18, digest(bytes)]));
|
|
9234
11558
|
}
|
|
9235
|
-
if (
|
|
11559
|
+
if (native) identity.update(JSON.stringify(native.metadata));
|
|
9236
11560
|
const releaseKey = `${prefix}/peach/releases/${identity.digest("hex")}`;
|
|
9237
11561
|
const assetBaseUrl = `${origin.origin}/${releaseKey}/`;
|
|
9238
11562
|
const directories = new Set(
|
|
9239
|
-
[...files2.keys()].map((
|
|
11563
|
+
[...files2.keys()].map((path18) => path18.slice(0, path18.lastIndexOf("/")))
|
|
9240
11564
|
);
|
|
9241
11565
|
let locations = 0;
|
|
9242
11566
|
let source = new TextDecoder("utf-8", { fatal: true }).decode(bundle).replace(
|
|
@@ -9244,36 +11568,46 @@ function prepareBundleChannel({
|
|
|
9244
11568
|
/("?httpServerLocation"?\s*:\s*)(?:"((?:[^"\\]|\\.)*)"|`([^`\\$]*)`)/g,
|
|
9245
11569
|
(match, property, quoted, template) => {
|
|
9246
11570
|
const location = quoted === void 0 ? template : JSON.parse(`"${quoted}"`);
|
|
9247
|
-
const
|
|
9248
|
-
if (
|
|
9249
|
-
throw new Error(`non-packaged asset location: ${location}`);
|
|
9250
|
-
const path16 = (parsed.searchParams.get("unstable_path") ?? parsed.pathname).replace(/^\/+/, "").replace(/\.\.\//g, "_");
|
|
9251
|
-
if (!directories.has(path16)) {
|
|
11571
|
+
const path18 = packagedAssetDirectory(location);
|
|
11572
|
+
if (!directories.has(path18)) {
|
|
9252
11573
|
throw new Error(`bundle asset location has no packaged files: ${location}`);
|
|
9253
11574
|
}
|
|
9254
11575
|
locations++;
|
|
9255
|
-
return `${property}${JSON.stringify(new URL(
|
|
11576
|
+
return `${property}${JSON.stringify(new URL(path18, assetBaseUrl).href)}`;
|
|
9256
11577
|
}
|
|
9257
11578
|
);
|
|
9258
11579
|
if (assets2.length && !locations)
|
|
9259
11580
|
throw new Error("bundle has packaged files but no asset metadata");
|
|
11581
|
+
const release = (url) => new URL(url.replace(/^\//, ""), assetBaseUrl).href;
|
|
9260
11582
|
let nativeMetadata = null;
|
|
9261
11583
|
if (expoSwift) {
|
|
9262
11584
|
nativeMetadata = {
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
11585
|
+
expoSwift: {
|
|
11586
|
+
...expoSwift.metadata,
|
|
11587
|
+
modules: expoSwift.metadata.modules.map((artifact) => ({
|
|
11588
|
+
...artifact,
|
|
11589
|
+
url: release(artifact.url),
|
|
11590
|
+
icuUrl: artifact.icuUrl.startsWith("/") ? release(artifact.icuUrl) : artifact.icuUrl
|
|
11591
|
+
}))
|
|
11592
|
+
}
|
|
11593
|
+
};
|
|
11594
|
+
source = insertExpoSwiftFooter(source, nativeMetadata.expoSwift);
|
|
11595
|
+
}
|
|
11596
|
+
if (expoKotlin) {
|
|
11597
|
+
const { module: module2 } = expoKotlin.metadata;
|
|
11598
|
+
nativeMetadata = {
|
|
11599
|
+
expoKotlin: {
|
|
11600
|
+
...expoKotlin.metadata,
|
|
11601
|
+
module: module2 && { ...module2, url: release(module2.url) }
|
|
11602
|
+
}
|
|
9269
11603
|
};
|
|
9270
|
-
source =
|
|
11604
|
+
source = insertExpoKotlinFooter(source, nativeMetadata.expoKotlin);
|
|
9271
11605
|
}
|
|
9272
11606
|
new import_node_vm.Script(source, { filename: "peach-release-bundle.js" });
|
|
9273
11607
|
const bundleBytes = Buffer.from(source);
|
|
9274
11608
|
const metadata = {
|
|
9275
11609
|
schemaVersion: 1,
|
|
9276
|
-
...nativeMetadata
|
|
11610
|
+
...nativeMetadata,
|
|
9277
11611
|
channel: "prod",
|
|
9278
11612
|
name: name2,
|
|
9279
11613
|
iconUrl: `${assetBaseUrl}icon.png`,
|
|
@@ -9281,7 +11615,7 @@ function prepareBundleChannel({
|
|
|
9281
11615
|
assetBaseUrl,
|
|
9282
11616
|
sourceSha,
|
|
9283
11617
|
runtimeVersion,
|
|
9284
|
-
platform
|
|
11618
|
+
platform,
|
|
9285
11619
|
bundleHash: digest(bundleBytes)
|
|
9286
11620
|
};
|
|
9287
11621
|
const objects = [
|
|
@@ -9291,10 +11625,10 @@ function prepareBundleChannel({
|
|
|
9291
11625
|
contentType: "application/javascript"
|
|
9292
11626
|
},
|
|
9293
11627
|
{ key: `${releaseKey}/icon.png`, bytes: icon, contentType: "image/png" },
|
|
9294
|
-
...[...files2].map(([
|
|
9295
|
-
key: `${releaseKey}/${
|
|
11628
|
+
...[...files2].map(([path18, bytes]) => ({
|
|
11629
|
+
key: `${releaseKey}/${path18}`,
|
|
9296
11630
|
bytes,
|
|
9297
|
-
contentType:
|
|
11631
|
+
contentType: native?.assets.find((asset) => asset.path === path18)?.contentType ?? {
|
|
9298
11632
|
png: "image/png",
|
|
9299
11633
|
jpg: "image/jpeg",
|
|
9300
11634
|
jpeg: "image/jpeg",
|
|
@@ -9303,51 +11637,104 @@ function prepareBundleChannel({
|
|
|
9303
11637
|
ttf: "font/ttf",
|
|
9304
11638
|
otf: "font/otf",
|
|
9305
11639
|
wav: "audio/wav"
|
|
9306
|
-
}[
|
|
11640
|
+
}[path18.split(".").pop()] ?? "application/octet-stream"
|
|
9307
11641
|
}))
|
|
9308
11642
|
];
|
|
9309
|
-
return {
|
|
11643
|
+
return { platform, key: `${prefix}/${channelKey(platform)}`, metadata, objects };
|
|
9310
11644
|
}
|
|
9311
11645
|
async function publishBundleChannel(release, { put, fetchObject = fetch }) {
|
|
9312
11646
|
async function uploadVerified(object, cacheControl) {
|
|
9313
11647
|
await put(object.key, object.bytes, object.contentType, cacheControl);
|
|
9314
|
-
const
|
|
9315
|
-
if (!
|
|
9316
|
-
throw new Error(`bundle channel download failed: ${
|
|
9317
|
-
const bytes = Buffer.from(await
|
|
11648
|
+
const response = await fetchObject(`${release.origin}/${object.key}`);
|
|
11649
|
+
if (!response.ok)
|
|
11650
|
+
throw new Error(`bundle channel download failed: ${response.status} ${object.key}`);
|
|
11651
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
9318
11652
|
if (digest(bytes) !== digest(object.bytes))
|
|
9319
11653
|
throw new Error(`bundle channel download mismatch: ${object.key}`);
|
|
9320
11654
|
}
|
|
9321
|
-
for (const
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
{ ...
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
11655
|
+
for (const channel of release.channels)
|
|
11656
|
+
for (const object of channel.objects) await uploadVerified(object);
|
|
11657
|
+
for (const channel of release.channels) {
|
|
11658
|
+
await uploadVerified({ ...channel.objects[0], key: `${channel.key}.js` }, "no-store");
|
|
11659
|
+
await put(
|
|
11660
|
+
`${channel.key}.json`,
|
|
11661
|
+
Buffer.from(JSON.stringify(channel.metadata)),
|
|
11662
|
+
"application/json",
|
|
11663
|
+
"no-store"
|
|
11664
|
+
);
|
|
11665
|
+
const response = await fetchObject(`${release.origin}/${channel.key}.json`, {
|
|
11666
|
+
cache: "no-store"
|
|
11667
|
+
});
|
|
11668
|
+
if (!response.ok || JSON.stringify(await response.json()) !== JSON.stringify(channel.metadata)) {
|
|
11669
|
+
throw new Error(
|
|
11670
|
+
`published ${channel.platform} bundle channel metadata did not match`
|
|
11671
|
+
);
|
|
11672
|
+
}
|
|
11673
|
+
console.log(
|
|
11674
|
+
`[ota] Peach ${channel.platform} prod channel: ${release.origin}/${channel.key}.json`
|
|
11675
|
+
);
|
|
9339
11676
|
}
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
11677
|
+
}
|
|
11678
|
+
async function snapshotDevServerBundles(origin, projectRoot, { platforms = ["ios", "android"], assertRunning = () => {
|
|
11679
|
+
} } = {}) {
|
|
11680
|
+
const { readFileSync: readFileSync5 } = await import("node:fs");
|
|
11681
|
+
const { basename: basename2 } = await import("node:path");
|
|
11682
|
+
const snapshots = [];
|
|
11683
|
+
for (const platform of platforms) {
|
|
11684
|
+
const url = `${origin}/index.bundle?platform=${platform}&dev=true&minify=false`;
|
|
11685
|
+
const deadline = Date.now() + 10 * 6e4;
|
|
11686
|
+
let bundle;
|
|
11687
|
+
while (!bundle) {
|
|
11688
|
+
assertRunning();
|
|
11689
|
+
if (Date.now() > deadline)
|
|
11690
|
+
throw new Error(`dev server ${platform} bundle timed out`);
|
|
11691
|
+
const response = await fetch(url).catch(() => null);
|
|
11692
|
+
if (response?.ok) bundle = Buffer.from(await response.arrayBuffer());
|
|
11693
|
+
else await new Promise((resolve2) => setTimeout(resolve2, 2e3));
|
|
11694
|
+
}
|
|
11695
|
+
const assets2 = /* @__PURE__ */ new Map();
|
|
11696
|
+
for (const [registration] of bundle.toString("utf8").matchAll(/(?<=registerAsset\()\{[^{}]*"__packager_asset": true[^{}]*\}/g)) {
|
|
11697
|
+
const asset = JSON.parse(registration);
|
|
11698
|
+
const directory = packagedAssetDirectory(asset.httpServerLocation);
|
|
11699
|
+
if (asset.files) {
|
|
11700
|
+
for (const file of asset.files) {
|
|
11701
|
+
const path18 = `${directory}/${basename2(file)}`;
|
|
11702
|
+
if (!assets2.has(path18)) assets2.set(path18, readFileSync5(file));
|
|
11703
|
+
}
|
|
11704
|
+
continue;
|
|
11705
|
+
}
|
|
11706
|
+
for (const scale of asset.scales) {
|
|
11707
|
+
const file = `${asset.name}${scale === 1 ? "" : `@${scale}x`}.${asset.type}`;
|
|
11708
|
+
const path18 = `${directory}/${file}`;
|
|
11709
|
+
if (assets2.has(path18)) continue;
|
|
11710
|
+
const response = await fetch(
|
|
11711
|
+
`${origin}${asset.httpServerLocation}/${file}?platform=${platform}&hash=${asset.hash}`
|
|
11712
|
+
);
|
|
11713
|
+
if (!response.ok)
|
|
11714
|
+
throw new Error(`dev server asset ${path18} failed: ${response.status}`);
|
|
11715
|
+
assets2.set(path18, Buffer.from(await response.arrayBuffer()));
|
|
11716
|
+
}
|
|
11717
|
+
}
|
|
11718
|
+
snapshots.push({
|
|
11719
|
+
platform,
|
|
11720
|
+
bundle,
|
|
11721
|
+
assets: [...assets2].map(([path18, bytes]) => ({ path: path18, bytes })),
|
|
11722
|
+
...platform === "ios" ? {
|
|
11723
|
+
expoSwift: await (await Promise.resolve().then(() => (init_expo_swift_bundle(), expo_swift_bundle_exports))).buildExpoSwiftBundle(projectRoot)
|
|
11724
|
+
} : {
|
|
11725
|
+
expoKotlin: await (await Promise.resolve().then(() => (init_expo_kotlin_bundle(), expo_kotlin_bundle_exports))).buildExpoKotlinBundle(projectRoot)
|
|
11726
|
+
}
|
|
11727
|
+
});
|
|
11728
|
+
}
|
|
11729
|
+
return { platforms: snapshots };
|
|
9343
11730
|
}
|
|
9344
11731
|
async function snapshotOneDevBundle(projectRoot, env = {}) {
|
|
9345
11732
|
const { spawn: spawn2 } = await import("node:child_process");
|
|
9346
11733
|
const { readFileSync: readFileSync5 } = await import("node:fs");
|
|
9347
11734
|
const { createServer } = await import("node:net");
|
|
9348
|
-
const {
|
|
9349
|
-
const { createRequire:
|
|
9350
|
-
const onePackage =
|
|
11735
|
+
const { dirname: dirname2, join: join2 } = await import("node:path");
|
|
11736
|
+
const { createRequire: createRequire4 } = await import("node:module");
|
|
11737
|
+
const onePackage = createRequire4(join2(projectRoot, "package.json")).resolve(
|
|
9351
11738
|
"one/package.json"
|
|
9352
11739
|
);
|
|
9353
11740
|
const oneBin = join2(
|
|
@@ -9367,32 +11754,12 @@ async function snapshotOneDevBundle(projectRoot, env = {}) {
|
|
|
9367
11754
|
detached: true
|
|
9368
11755
|
});
|
|
9369
11756
|
try {
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
if (child.exitCode !== null)
|
|
9375
|
-
throw new Error(`one dev exited with ${child.exitCode}`);
|
|
9376
|
-
if (Date.now() > deadline) throw new Error("one dev bundle timed out");
|
|
9377
|
-
const response = await fetch(url).catch(() => null);
|
|
9378
|
-
if (response?.ok) bundle = Buffer.from(await response.arrayBuffer());
|
|
9379
|
-
else await new Promise((resolve2) => setTimeout(resolve2, 2e3));
|
|
9380
|
-
}
|
|
9381
|
-
const assets2 = /* @__PURE__ */ new Map();
|
|
9382
|
-
for (const [registration] of bundle.toString("utf8").matchAll(/(?<=registerAsset\()\{[^{}]*"__packager_asset": true[^{}]*\}/g)) {
|
|
9383
|
-
const asset = JSON.parse(registration);
|
|
9384
|
-
for (const file of asset.files) {
|
|
9385
|
-
const path16 = `${asset.httpServerLocation.replace(/^\/+/, "")}/${basename2(file)}`;
|
|
9386
|
-
if (!assets2.has(path16)) assets2.set(path16, readFileSync5(file));
|
|
11757
|
+
return await snapshotDevServerBundles(`http://127.0.0.1:${port}`, projectRoot, {
|
|
11758
|
+
assertRunning: () => {
|
|
11759
|
+
if (child.exitCode !== null)
|
|
11760
|
+
throw new Error(`one dev exited with ${child.exitCode}`);
|
|
9387
11761
|
}
|
|
9388
|
-
}
|
|
9389
|
-
const { buildExpoSwiftBundle: buildExpoSwiftBundle2 } = await Promise.resolve().then(() => (init_expo_swift_bundle(), expo_swift_bundle_exports));
|
|
9390
|
-
const expoSwift = await buildExpoSwiftBundle2(projectRoot);
|
|
9391
|
-
return {
|
|
9392
|
-
bundle,
|
|
9393
|
-
assets: [...assets2].map(([path16, bytes]) => ({ path: path16, bytes })),
|
|
9394
|
-
expoSwift
|
|
9395
|
-
};
|
|
11762
|
+
});
|
|
9396
11763
|
} finally {
|
|
9397
11764
|
await terminateProcessGroup(child);
|
|
9398
11765
|
}
|
|
@@ -9401,5 +11768,6 @@ async function snapshotOneDevBundle(projectRoot, env = {}) {
|
|
|
9401
11768
|
0 && (module.exports = {
|
|
9402
11769
|
prepareBundleChannel,
|
|
9403
11770
|
publishBundleChannel,
|
|
11771
|
+
snapshotDevServerBundles,
|
|
9404
11772
|
snapshotOneDevBundle
|
|
9405
11773
|
});
|