peachsim 0.1.939 → 0.1.1399
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -22
- package/cli/app-catalog.ts +29 -14
- package/cli/app-fonts.ts +5 -3
- package/cli/bridge-flow-runner.ts +40 -29
- package/cli/cloud-client.ts +57 -21
- package/cli/cloud-test-tunnel.ts +12 -18
- package/cli/commands/agent.ts +1 -1
- package/cli/commands/app-fonts.ts +3 -3
- package/cli/commands/assert.ts +8 -8
- package/cli/commands/auth.ts +8 -3
- package/cli/commands/box/bundle-plane.ts +13 -1
- package/cli/commands/box.ts +16 -5
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +125 -71
- package/cli/commands/cpu-profile.ts +45 -1
- package/cli/commands/daemon.ts +131 -33
- package/cli/commands/debug.ts +24 -17
- package/cli/commands/desktop.ts +7 -1
- package/cli/commands/detect.ts +101 -0
- package/cli/commands/detox.ts +6 -6
- package/cli/commands/device.ts +12 -12
- package/cli/commands/electron.ts +32 -14
- package/cli/commands/flow.ts +49 -41
- package/cli/commands/guest-host.ts +39 -1
- package/cli/commands/inspect/core.ts +14 -8
- package/cli/commands/inspect/list.ts +1 -1
- package/cli/commands/inspect/settle.ts +5 -3
- package/cli/commands/inspect/settling.ts +229 -44
- package/cli/commands/inspect/wait-idle.ts +3 -2
- package/cli/commands/inspect.ts +105 -93
- package/cli/commands/install-cli.ts +36 -15
- package/cli/commands/install-desktop.ts +68 -195
- package/cli/commands/kotlin.ts +6 -5
- package/cli/commands/login.ts +5 -5
- package/cli/commands/maestro-compare.ts +554 -0
- package/cli/commands/maestro-generate.ts +6 -3
- package/cli/commands/maestro.ts +22 -0
- package/cli/commands/mode.ts +2 -2
- package/cli/commands/no-bridge-hint.ts +6 -2
- package/cli/commands/platform.ts +35 -6
- package/cli/commands/preview.ts +6 -0
- package/cli/commands/project-report.ts +10 -12
- package/cli/commands/record.ts +37 -37
- package/cli/commands/runtime.ts +9 -9
- package/cli/commands/screenshot-layers.ts +4 -4
- package/cli/commands/screenshot-mode.ts +2 -2
- package/cli/commands/screenshot.ts +8 -8
- package/cli/commands/screenshots-capture.ts +2 -2
- package/cli/commands/serve.ts +9 -12
- package/cli/commands/setup.ts +29 -14
- package/cli/commands/shell-boolean-mode.ts +2 -2
- package/cli/commands/show-touches-mode.ts +2 -2
- package/cli/commands/skills.ts +11 -11
- package/cli/commands/swift.ts +29 -11
- package/cli/commands/telemetry.ts +2 -2
- package/cli/commands/test.ts +5 -0
- package/cli/commands/three-mode.ts +3 -3
- package/cli/commands/timeline.ts +4 -4
- package/cli/commands/upgrade.ts +2 -2
- package/cli/commands/upload.ts +15 -15
- package/cli/commands/what-happened.ts +2 -2
- package/cli/current-sim.ts +6 -3
- package/cli/desktop-companion.ts +55 -149
- package/cli/dev-build-freshness.ts +2 -2
- package/cli/drivers/desktop.ts +17 -9
- package/cli/drivers/electron.ts +1 -2
- package/cli/drivers/playwright-sim-host.ts +11 -2
- package/cli/drivers/playwright.ts +35 -2
- package/cli/drivers/types.ts +8 -0
- package/cli/maestro-compare.ts +670 -0
- package/cli/outbound-endpoints.ts +46 -8
- package/cli/recording-access.ts +6 -6
- package/cli/run-registry.ts +1 -1
- package/cli/runtime-compat.ts +5 -1
- package/cli/send-to-box.ts +3 -3
- package/cli/shell-init.ts +2 -1
- package/cli/ws-bridge.ts +9 -5
- package/detox/element-types.ts +1 -0
- package/detox/gestures.ts +3 -3
- package/detox/index.ts +67 -38
- package/detox/navigation-lifecycle.ts +9 -6
- package/detox/proof-frame.cjs +6 -4
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +42 -17
- package/dist-lib/bridge-contract-input.mjs +41 -16
- package/dist-lib/bridge-contract.cjs +1 -4
- package/dist-lib/bridge-contract.mjs +1 -3
- package/dist-lib/bundle-channel.cjs +2918 -550
- package/dist-lib/capture-contract.cjs +65 -24
- package/dist-lib/capture-contract.mjs +63 -24
- package/dist-lib/cloud-contract.cjs +2 -2
- package/dist-lib/cloud-contract.mjs +2 -2
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +3 -3
- package/dist-lib/cloud.mjs +3 -3
- package/dist-lib/config.cjs +15 -5
- package/dist-lib/config.mjs +154 -0
- package/dist-lib/detox/index.cjs +495 -139
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +1168 -238
- package/dist-lib/expo-swift-metadata.cjs +34 -23
- package/dist-lib/expo-swift-metadata.mjs +32 -23
- package/dist-lib/home-paths.cjs +2 -2
- package/dist-lib/host/bridge-host.cjs +2938 -654
- package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
- package/dist-lib/host/replacement-module-handler.cjs +2 -2
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +999 -353
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +332 -19
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +7 -7
- package/dist-lib/metro-production-bundle.mjs +5 -5
- package/dist-lib/metro.cjs +688 -250
- package/dist-lib/native-app-identity-project.cjs +2647 -0
- package/dist-lib/native-app-identity-project.mjs +1257 -0
- package/dist-lib/native-app-identity.cjs +325 -25
- package/dist-lib/native-app-identity.mjs +323 -25
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +5 -1
- package/dist-lib/react-native-host-modules.mjs +5 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
- package/dist-lib/sdk.cjs +231 -51
- package/dist-lib/sdk.mjs +231 -51
- package/dist-lib/skills.cjs +4107 -1374
- package/dist-lib/swift-compile.cjs +290 -30
- package/dist-lib/swift-compile.mjs +290 -30
- package/dist-lib/swift-package.cjs +143 -12
- package/dist-lib/swift-package.mjs +137 -11
- package/dist-lib/swift-submit.cjs +47 -5
- package/dist-lib/swift-submit.mjs +42 -5
- package/dist-lib/swift-toolchain.cjs +7 -2
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1392 -458
- package/dist-lib/vite.cjs +13 -17
- package/dist-lib/worklet-executable.cjs +248 -33
- package/dist-lib/worklet-executable.mjs +248 -33
- package/install.sh +10 -1
- package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
- package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
- package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
- package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
- package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
- package/kotlin/AppSources/android/view/Window.kt +36 -0
- package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
- package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
- package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
- package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
- package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
- package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
- package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
- package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
- package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
- package/kotlin/README.md +13 -3
- package/kotlin/Sources/android/os/Build.kt +17 -0
- package/kotlin/Sources/android/os/Handler.kt +35 -0
- package/kotlin/Sources/android/os/Looper.kt +17 -0
- package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
- package/kotlin/Sources/android/os/SystemClock.kt +14 -0
- package/kotlin/Sources/android/util/Log.kt +64 -0
- package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
- package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
- package/kotlin/Sources/org/json/JSON.kt +44 -0
- package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
- package/kotlin/fixtures/counter/Counter.kt +10 -3
- package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
- package/kotlin/fixtures/counter/vite.config.ts +2 -2
- package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
- package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-animation/Animation.kt +80 -0
- package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
- package/kotlin/fixtures/import-animation/README.md +24 -0
- package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
- package/kotlin/fixtures/import-animation/package.json +23 -0
- package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
- package/kotlin/fixtures/import-editor/Editor.kt +59 -0
- package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
- package/kotlin/fixtures/import-editor/README.md +27 -0
- package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-editor/package.json +23 -0
- package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
- package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
- package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
- package/kotlin/fixtures/import-effects/Effects.kt +87 -0
- package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
- package/kotlin/fixtures/import-effects/README.md +19 -0
- package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-effects/package.json +23 -0
- package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
- package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
- package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
- package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
- package/kotlin/fixtures/import-layout/Layout.kt +72 -0
- package/kotlin/fixtures/import-layout/README.md +24 -0
- package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-layout/package.json +23 -0
- package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
- package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
- package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
- package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
- package/kotlin/fixtures/import-navigation/README.md +31 -0
- package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-navigation/package.json +23 -0
- package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
- package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
- package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
- package/kotlin/fixtures/import-overlays/README.md +34 -0
- package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-overlays/package.json +23 -0
- package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
- package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
- package/kotlin/fixtures/import-scroll/README.md +23 -0
- package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
- package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
- package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-scroll/package.json +23 -0
- package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
- package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
- package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
- package/kotlin/fixtures/import-selection/README.md +32 -0
- package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
- package/kotlin/fixtures/import-selection/Selection.kt +78 -0
- package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-selection/package.json +23 -0
- package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
- package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
- package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
- package/kotlin/fixtures/import-surfaces/README.md +22 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
- package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-surfaces/package.json +23 -0
- package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
- package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
- package/kotlin/fixtures/import-values/README.md +23 -0
- package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
- package/kotlin/fixtures/import-values/Values.kt +66 -0
- package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/package.json +23 -0
- package/kotlin/fixtures/import-values/tsconfig.json +20 -0
- package/kotlin/fixtures/import-values/vite.config.ts +20 -0
- package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
- package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
- package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
- package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
- package/kotlin/fork/NOTICE +6 -1
- package/kotlin/fork/README.md +15 -7
- package/kotlin/fork/build.sh +2 -0
- package/kotlin/fork/compose-worker-globals.patch +186 -4
- package/kotlin/fork/fork.json +2 -2
- package/kotlin/fork/skiko-worker-clock.patch +12 -0
- package/kotlin/toolchain.json +12 -12
- package/kotlin/tools/expo-types.main.kts +115 -0
- package/package.json +17 -23
- package/scripts/dev-server-scanner.ts +92 -66
- package/skills/contrast/SKILL.md +2 -2
- package/skills/peach-debug/SKILL.md +1 -1
- package/skills/peach-perf/SKILL.md +1 -1
- package/skills/peach-setup/SKILL.md +2 -1
- package/skills/peach-test/SKILL.md +8 -0
- package/src/assetCatalogContract.ts +43 -1
- package/src/bridge-contract-input.ts +46 -19
- package/src/bridge-contract.ts +0 -1
- package/src/bundle-channel.mjs +197 -84
- package/src/bundleGlobalFooter.ts +38 -0
- package/src/capture-contract.ts +107 -33
- package/src/cloud-contract.ts +5 -1
- package/src/cloud.ts +5 -2
- package/src/config.ts +22 -3
- package/src/configured-bundle-producer.ts +1 -1
- package/src/desktop-host-delivery.ts +95 -1
- package/src/expo-kotlin-bundle.ts +29 -0
- package/src/expo-kotlin-host.ts +201 -0
- package/src/expo-swift-host.ts +96 -76
- package/src/expoKotlinContract.ts +70 -0
- package/src/expoSwiftContract.ts +4 -25
- package/src/home-paths.ts +7 -4
- package/src/host/bridge-host.ts +23 -3
- package/src/host/fetch-proxy-handler.ts +13 -0
- package/src/host/fetch-proxy-overrides.ts +11 -0
- package/src/host/replacement-module-handler.ts +5 -2
- package/src/index.ts +3 -1
- package/src/kotlin-host.ts +463 -19
- package/src/metro-plugin.ts +56 -28
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-app-identity-project.ts +190 -0
- package/src/native-app-identity.ts +398 -34
- package/src/native-firebase-config.ts +69 -15
- package/src/native-seam-manifest.ts +6 -0
- package/src/one-widget-discovery.ts +2 -1
- package/src/openstep-plist.ts +107 -0
- package/src/react-native-host-modules.ts +4 -0
- package/src/runtime-assets.ts +2 -2
- package/src/sim-client.ts +2 -2
- package/src/swift-binary-modules.ts +3 -1
- package/src/swift-compile.ts +286 -38
- package/src/swift-distribution-contract.ts +4 -0
- package/src/swift-distribution.lock.json +123 -12
- package/src/swift-distribution.ts +7 -3
- package/src/swift-host.ts +298 -83
- package/src/swift-package-manifest.ts +29 -2
- package/src/swift-package.ts +180 -10
- package/src/swift-packages.ts +4 -0
- package/src/swift-standin-emit.ts +4 -1
- package/src/swift-standins.ts +274 -15
- package/src/swift-submit.ts +62 -7
- package/src/swift-toolchain.ts +6 -1
- package/src/swiftContract.ts +126 -3
- package/src/vite-plugin-one.ts +13 -16
- package/src/vite-plugin-swift.ts +4 -5
- package/src/vite-plugin.ts +360 -144
- package/src/vite.d.ts +1 -1
- package/src/worker-system-chunks.ts +221 -0
- package/src/worklet-executable.ts +348 -38
- package/src/worklets-babel.ts +1 -1
- package/src/xcode-project.ts +243 -127
- package/dist-lib/agent-identity.cjs +0 -39
- package/dist-lib/agent-sessions.cjs +0 -760
- package/dist-lib/cli-constants.cjs +0 -32
- package/dist-lib/render-mode.cjs +0 -44
- package/kotlin/AppSources/android/view/View.kt +0 -74
- package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
- package/src/render-mode.ts +0 -15
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
- /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
package/src/vite-plugin.ts
CHANGED
|
@@ -14,8 +14,10 @@ import { createRequire } from 'module'
|
|
|
14
14
|
import { runInNewContext, Script } from 'node:vm'
|
|
15
15
|
import path from 'path'
|
|
16
16
|
import { fileURLToPath, pathToFileURL } from 'url'
|
|
17
|
-
import {
|
|
17
|
+
import { parseSync } from 'oxc-parser'
|
|
18
|
+
import { minifySync, transformSync } from 'rolldown/utils'
|
|
18
19
|
import { type Plugin, transformWithOxc } from 'vite'
|
|
20
|
+
import { renderWorkerSystemChunk } from './worker-system-chunks.ts'
|
|
19
21
|
|
|
20
22
|
declare module '@babel/core' {
|
|
21
23
|
interface TransformCaller {
|
|
@@ -34,7 +36,10 @@ import {
|
|
|
34
36
|
reactNativeDeepStubsForBuildResolver,
|
|
35
37
|
} from '../../peach-compat/src/stub-manifest.ts'
|
|
36
38
|
import { WEBVIEW_SAME_ORIGIN_BOOTSTRAP_SOURCE } from '../../peach-engine/src/components/native-ui/webview-frame-bridge.ts'
|
|
37
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
isExpoHostSocketModule,
|
|
41
|
+
isReactNativeEnvironmentSetupModule,
|
|
42
|
+
} from '../../peach-engine/src/guest-module-overrides.ts'
|
|
38
43
|
import { readPeachWarmManifest } from '../../peach-engine/src/peach-warm-manifest.ts'
|
|
39
44
|
import { resolveSootsimBridgePort } from './bridge-constants.ts'
|
|
40
45
|
import { isRecord } from './is-record.ts'
|
|
@@ -91,6 +96,10 @@ const sootsimBrowserSourceAliases = [
|
|
|
91
96
|
find: 'peachsim/bridge-constants',
|
|
92
97
|
replacement: path.resolve(sootsimRoot, 'src/bridge-constants.ts'),
|
|
93
98
|
},
|
|
99
|
+
{
|
|
100
|
+
find: 'peachsim/config',
|
|
101
|
+
replacement: path.resolve(sootsimRoot, 'src/config.ts'),
|
|
102
|
+
},
|
|
94
103
|
{
|
|
95
104
|
find: 'peachsim/dev-bundle-resolution',
|
|
96
105
|
replacement: path.resolve(sootsimRoot, 'src/dev-bundle-resolution.ts'),
|
|
@@ -136,6 +145,19 @@ const rnLibraryStubs = Object.fromEntries(
|
|
|
136
145
|
]),
|
|
137
146
|
)
|
|
138
147
|
|
|
148
|
+
function resolveReactNativeLibraryStub(source: string, importer?: string) {
|
|
149
|
+
const candidate =
|
|
150
|
+
source.startsWith('.') && importer
|
|
151
|
+
? path.resolve(path.dirname(stripViteQuery(importer)), stripViteQuery(source))
|
|
152
|
+
: stripViteQuery(source)
|
|
153
|
+
const match = /(?:^|\/)(react-native\/Libraries\/.+)$/.exec(candidate)
|
|
154
|
+
if (!match) return undefined
|
|
155
|
+
const specifier = match[1]
|
|
156
|
+
.replace(/\.(?:[cm]?[jt]sx?)$/, '')
|
|
157
|
+
.replace(/\.(?:native|web|ios|android)$/, '')
|
|
158
|
+
return rnLibraryStubs[specifier]
|
|
159
|
+
}
|
|
160
|
+
|
|
139
161
|
type PublishedBrowserPackage = {
|
|
140
162
|
specifier: string
|
|
141
163
|
packageDir: string
|
|
@@ -356,7 +378,7 @@ export function sootsim(options: SootSimOptions = {}): Plugin[] {
|
|
|
356
378
|
},
|
|
357
379
|
},
|
|
358
380
|
sootsimConfigPlugin(appDir, extraSources, publishedBrowserPackages),
|
|
359
|
-
|
|
381
|
+
hostEnvironmentBootstrapRedirect(),
|
|
360
382
|
fixJsxRuntimeExports(),
|
|
361
383
|
flowStripTransform(),
|
|
362
384
|
nodeModulesJsxTransform(),
|
|
@@ -375,31 +397,56 @@ export function sootsim(options: SootSimOptions = {}): Plugin[] {
|
|
|
375
397
|
metroNativeResolve(isAppSource),
|
|
376
398
|
reactNativeRequirePlugin(isAppSource),
|
|
377
399
|
...(appDir ? [externalAppResolvePlugin(appDir, isAppSource, ownedPackages)] : []),
|
|
378
|
-
|
|
379
|
-
? [externalAppTransformPlugin(isAppSource)]
|
|
380
|
-
: []),
|
|
400
|
+
externalAppTransformPlugin(isAppSource),
|
|
381
401
|
stubMissingNativeDeps(appDir),
|
|
382
402
|
stubMissingImages(isAppSource),
|
|
383
403
|
]
|
|
384
404
|
}
|
|
385
405
|
|
|
386
|
-
function
|
|
387
|
-
const target = '\
|
|
406
|
+
function hostEnvironmentBootstrapRedirect(): Plugin {
|
|
407
|
+
const target = '\0peach:host-environment-bootstrap'
|
|
408
|
+
const isHostBootstrap = (id: string) =>
|
|
409
|
+
isExpoHostSocketModule(id) ||
|
|
410
|
+
((id.startsWith('react-native/') || id.includes('/react-native/')) &&
|
|
411
|
+
isReactNativeEnvironmentSetupModule(id))
|
|
388
412
|
return {
|
|
389
|
-
name: '
|
|
413
|
+
name: 'peach-host-environment-bootstrap',
|
|
390
414
|
enforce: 'pre',
|
|
391
415
|
resolveId(source, importer) {
|
|
392
|
-
if (
|
|
416
|
+
if (source === target || isHostBootstrap(stripViteQuery(source))) return target
|
|
393
417
|
if (!importer || !source.startsWith('.')) return null
|
|
394
418
|
const candidate = path.resolve(
|
|
395
419
|
path.dirname(stripViteQuery(importer)),
|
|
396
420
|
stripViteQuery(source),
|
|
397
421
|
)
|
|
398
|
-
return
|
|
422
|
+
return isHostBootstrap(candidate) ? target : null
|
|
399
423
|
},
|
|
400
424
|
load(id) {
|
|
401
425
|
if (id !== target) return null
|
|
402
|
-
return 'export default function
|
|
426
|
+
return 'export default function noopHostEnvironmentBootstrap() {}'
|
|
427
|
+
},
|
|
428
|
+
transform: {
|
|
429
|
+
filter: { id: /\/node_modules\//, code: /require\(/ },
|
|
430
|
+
handler(code, id) {
|
|
431
|
+
let changed = false
|
|
432
|
+
const rewritten = code.replace(
|
|
433
|
+
/\brequire\((['"])([^'"]+)\1\)/g,
|
|
434
|
+
(call, _quote, source: string) => {
|
|
435
|
+
const candidate = source.startsWith('.')
|
|
436
|
+
? path.resolve(path.dirname(stripViteQuery(id)), source)
|
|
437
|
+
: source
|
|
438
|
+
if (!isHostBootstrap(candidate)) return call
|
|
439
|
+
changed = true
|
|
440
|
+
return '__peach_host_bootstrap__'
|
|
441
|
+
},
|
|
442
|
+
)
|
|
443
|
+
return changed
|
|
444
|
+
? {
|
|
445
|
+
code: `import * as __peach_host_bootstrap__ from ${JSON.stringify(target)};\n${rewritten}`,
|
|
446
|
+
map: null,
|
|
447
|
+
}
|
|
448
|
+
: null
|
|
449
|
+
},
|
|
403
450
|
},
|
|
404
451
|
}
|
|
405
452
|
}
|
|
@@ -575,24 +622,20 @@ function warmManifestJsonPlugin(): Plugin {
|
|
|
575
622
|
}
|
|
576
623
|
}
|
|
577
624
|
|
|
578
|
-
//
|
|
579
|
-
//
|
|
580
|
-
//
|
|
581
|
-
//
|
|
582
|
-
//
|
|
583
|
-
//
|
|
584
|
-
//
|
|
585
|
-
// dynamic boundary (see shell-worker-entry.ts); with every chunk inlined no
|
|
586
|
-
// other file can import the worker script, so nothing can evaluate it twice.
|
|
587
|
-
// inlined dynamic roots still evaluate at their `import()` (the reanimated
|
|
588
|
-
// passthrough must install before upstream reanimated, the worklet runtime
|
|
589
|
-
// must exist before shell-in-worker): with code splitting off rolldown wraps
|
|
590
|
-
// every dynamic-import target in an init function that runs on first import.
|
|
591
|
-
// shell-worker.ts throws at init if a bundle ever hoists one of them.
|
|
625
|
+
// workers load feature chunks on demand through one script-compatible module
|
|
626
|
+
// protocol. the entry owns its loader and remains a one-way bootstrap so lazy
|
|
627
|
+
// chunks never re-evaluate a worker's message listeners. the boot byte cap
|
|
628
|
+
// applies to that entry; cold Home proof also measures the downloaded startup
|
|
629
|
+
// graph and serial requests, since moving bytes into chunks alone is no gain.
|
|
630
|
+
// reanimated and shell-in-worker still evaluate at their original import()
|
|
631
|
+
// boundaries after the worklet runtime installs.
|
|
592
632
|
export type WorkerBootClosure = {
|
|
593
633
|
// substring of the worker entry module id this applies to
|
|
594
634
|
entry: string
|
|
595
|
-
//
|
|
635
|
+
// implementation roots loaded before Home; only their static dependencies
|
|
636
|
+
// share a chunk. other dynamic roots retain their first-use boundaries.
|
|
637
|
+
bootRoots?: readonly string[]
|
|
638
|
+
// byte cap on the rendered entry chunk; fix excess boot dependencies and
|
|
596
639
|
// unneeded inclusions rather than raising the cap.
|
|
597
640
|
// a cap failure in a worktree whose node_modules is symlinked from another
|
|
598
641
|
// tree is suspect: workspace modules resolve into the other tree and bundle
|
|
@@ -600,31 +643,57 @@ export type WorkerBootClosure = {
|
|
|
600
643
|
maxBytes: number
|
|
601
644
|
}
|
|
602
645
|
|
|
646
|
+
const SHELL_WORKER_BOOT_ROOTS = [
|
|
647
|
+
'src/render-worker/shell-worker-canvaskit.ts',
|
|
648
|
+
'src/render-worker/shell-worker.ts',
|
|
649
|
+
'src/render-worker/shell-reanimated-boot.ts',
|
|
650
|
+
'src/render-worker/shell-in-worker.tsx',
|
|
651
|
+
'src/render-worker/aux-roots.tsx',
|
|
652
|
+
'src/ios/HomeTreeRoot.tsx',
|
|
653
|
+
'src/ios/connect-app-icon.ts',
|
|
654
|
+
]
|
|
655
|
+
const COMPOSITOR_WORKER_BOOT_ROOTS = [
|
|
656
|
+
'src/render-worker/compositor-worker-adapter.ts',
|
|
657
|
+
'src/render-worker/compositor-worker.ts',
|
|
658
|
+
'src/render-worker/shell-tree-materializer.ts',
|
|
659
|
+
]
|
|
660
|
+
const GRAPHITE_WORKER_BOOT_ROOTS = [
|
|
661
|
+
'src/render-worker/canvaskit-webgpu.ts',
|
|
662
|
+
'src/render-worker/compositor-gpu-graphite.ts',
|
|
663
|
+
'vendor/canvaskit-graphite.js',
|
|
664
|
+
]
|
|
665
|
+
|
|
603
666
|
const ENGINE_WORKER_BOOT_CLOSURES: WorkerBootClosure[] = [
|
|
604
|
-
//
|
|
605
|
-
//
|
|
606
|
-
// parser is not reachable from any of them: only the tenant reads a face's
|
|
607
|
-
// name table, and it sends the aliases and metrics it read on the wire
|
|
667
|
+
// only the tenant reads a face's name table, and it sends the aliases and
|
|
668
|
+
// metrics it read on the wire
|
|
608
669
|
// (engine/app-font-registry.ts registerForwardedAppFonts). keep it that way
|
|
609
670
|
// when adding font work here, or every cap takes the parser again.
|
|
610
|
-
//
|
|
611
|
-
//
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
// each carries only its own CanvasKit glue: 3,263,311 graphite and
|
|
618
|
-
// 3,256,832 ganesh bytes when the split landed, down from 3,386,929 with both.
|
|
619
|
-
{ entry: 'src/render-worker/shell-worker-entry.ts', maxBytes: 3_310_000 },
|
|
671
|
+
// each entry selects one backend; its chunks retain only that backend's
|
|
672
|
+
// CanvasKit glue. feature imports keep their evaluation boundaries.
|
|
673
|
+
{
|
|
674
|
+
entry: 'src/render-worker/shell-worker-entry.ts',
|
|
675
|
+
maxBytes: 3_310_000,
|
|
676
|
+
bootRoots: [...SHELL_WORKER_BOOT_ROOTS, ...GRAPHITE_WORKER_BOOT_ROOTS],
|
|
677
|
+
},
|
|
620
678
|
// nate, 2026-10-06: "we can increase Ganesh. We can increase that to like 3.6",
|
|
621
679
|
// as work moves from the javascript into native code.
|
|
622
|
-
{
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
{
|
|
680
|
+
{
|
|
681
|
+
entry: 'src/render-worker/shell-worker-ganesh-entry.ts',
|
|
682
|
+
maxBytes: 3_600_000,
|
|
683
|
+
bootRoots: [...SHELL_WORKER_BOOT_ROOTS, 'vendor/canvaskit-ganesh.js'],
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
entry: 'src/render-worker/compositor-worker-entry.ts',
|
|
687
|
+
maxBytes: 1_200_000,
|
|
688
|
+
bootRoots: [...COMPOSITOR_WORKER_BOOT_ROOTS, ...GRAPHITE_WORKER_BOOT_ROOTS],
|
|
689
|
+
},
|
|
690
|
+
// both entries boot compositor-worker.ts with their backend and CanvasKit
|
|
691
|
+
// glue (plans/peach/compositor-one-path.md).
|
|
692
|
+
{
|
|
693
|
+
entry: 'src/render-worker/compositor-worker-ganesh-entry.ts',
|
|
694
|
+
maxBytes: 1_150_000,
|
|
695
|
+
bootRoots: [...COMPOSITOR_WORKER_BOOT_ROOTS, 'vendor/canvaskit-ganesh.js'],
|
|
696
|
+
},
|
|
628
697
|
]
|
|
629
698
|
|
|
630
699
|
// packages whose manifests omit `sideEffects` (metro never tree-shakes, so
|
|
@@ -644,9 +713,64 @@ const WORKER_SIDE_EFFECT_FREE_PACKAGES = [
|
|
|
644
713
|
},
|
|
645
714
|
]
|
|
646
715
|
|
|
716
|
+
function collectStaticBootModules(
|
|
717
|
+
context: {
|
|
718
|
+
getModuleIds(): IterableIterator<string>
|
|
719
|
+
getModuleInfo(id: string): { importedIds: string[] } | null
|
|
720
|
+
},
|
|
721
|
+
roots: readonly string[],
|
|
722
|
+
) {
|
|
723
|
+
const modules = new Set<string>()
|
|
724
|
+
const visit = (id: string) => {
|
|
725
|
+
if (modules.has(id)) return
|
|
726
|
+
modules.add(id)
|
|
727
|
+
for (const dependency of context.getModuleInfo(id)?.importedIds ?? [])
|
|
728
|
+
visit(dependency)
|
|
729
|
+
}
|
|
730
|
+
for (const id of context.getModuleIds())
|
|
731
|
+
if (roots.some((root) => id.endsWith(`/${root}`))) visit(id)
|
|
732
|
+
return modules
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// the host's already-eager static closure shares one download. optional host
|
|
736
|
+
// services keep their dynamic imports and ordered first-use evaluation.
|
|
737
|
+
export function hostBootChunkPlugin(): Plugin {
|
|
738
|
+
let modules = new Set<string>()
|
|
739
|
+
return {
|
|
740
|
+
name: 'peach-host-boot-chunk',
|
|
741
|
+
apply: 'build',
|
|
742
|
+
buildEnd(error) {
|
|
743
|
+
if (!error) {
|
|
744
|
+
modules = collectStaticBootModules(this, ['src/main.tsx'])
|
|
745
|
+
// the entry must retain its filename and manifest identity.
|
|
746
|
+
for (const id of modules) if (id.endsWith('/src/main.tsx')) modules.delete(id)
|
|
747
|
+
}
|
|
748
|
+
},
|
|
749
|
+
outputOptions(options) {
|
|
750
|
+
return {
|
|
751
|
+
...options,
|
|
752
|
+
// host resource urls are relative to the runtime root.
|
|
753
|
+
chunkFileNames: (chunk) =>
|
|
754
|
+
chunk.name === 'host-home' ? 'host-home-[hash].js' : 'assets/[name]-[hash].js',
|
|
755
|
+
strictExecutionOrder: true,
|
|
756
|
+
codeSplitting: {
|
|
757
|
+
groups: [
|
|
758
|
+
{
|
|
759
|
+
name: 'host-home',
|
|
760
|
+
test: (id) => modules.has(id),
|
|
761
|
+
includeDependenciesRecursively: false,
|
|
762
|
+
},
|
|
763
|
+
],
|
|
764
|
+
},
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
647
770
|
export function workerBootChunkPlugin(closures: WorkerBootClosure[]): Plugin {
|
|
648
771
|
let closure: WorkerBootClosure | null = null
|
|
649
772
|
let isWorker = false
|
|
773
|
+
let bootModules = new Set<string>()
|
|
650
774
|
return {
|
|
651
775
|
name: 'sootsim-worker-boot-chunk',
|
|
652
776
|
apply: 'build',
|
|
@@ -667,48 +791,59 @@ export function workerBootChunkPlugin(closures: WorkerBootClosure[]): Plugin {
|
|
|
667
791
|
treeshake: { ...treeshake, moduleSideEffects: WORKER_SIDE_EFFECT_FREE_PACKAGES },
|
|
668
792
|
}
|
|
669
793
|
},
|
|
794
|
+
buildEnd(error) {
|
|
795
|
+
if (!isWorker || error || !closure?.bootRoots) return
|
|
796
|
+
bootModules = collectStaticBootModules(this, closure.bootRoots)
|
|
797
|
+
},
|
|
670
798
|
outputOptions(options) {
|
|
671
799
|
if (!isWorker) return null
|
|
672
|
-
return {
|
|
800
|
+
return {
|
|
801
|
+
...options,
|
|
802
|
+
codeSplitting: closure?.bootRoots
|
|
803
|
+
? {
|
|
804
|
+
groups: [
|
|
805
|
+
{
|
|
806
|
+
name: 'worker-home',
|
|
807
|
+
test: (id) => bootModules.has(id),
|
|
808
|
+
includeDependenciesRecursively: false,
|
|
809
|
+
},
|
|
810
|
+
],
|
|
811
|
+
}
|
|
812
|
+
: true,
|
|
813
|
+
strictExecutionOrder: true,
|
|
814
|
+
format: 'es',
|
|
815
|
+
strict: true,
|
|
816
|
+
// keep retained chunk source one-byte even when literals contain unicode.
|
|
817
|
+
minify: { codegen: { asciiOnly: true } },
|
|
818
|
+
}
|
|
673
819
|
},
|
|
674
820
|
renderChunk: {
|
|
675
821
|
order: 'post',
|
|
676
822
|
async handler(code, chunk) {
|
|
677
823
|
if (!isWorker) return null
|
|
678
|
-
// vite
|
|
679
|
-
//
|
|
680
|
-
|
|
681
|
-
define: { 'import.meta.url': 'globalThis.location.href' },
|
|
682
|
-
sourcemap: true,
|
|
683
|
-
})
|
|
684
|
-
if (!transformed.map) this.error('worker transform produced no source map')
|
|
685
|
-
const compact = await minify(transformed.code, {
|
|
686
|
-
module: true,
|
|
687
|
-
compress: { passes: 4 },
|
|
688
|
-
mangle: true,
|
|
689
|
-
sourceMap: { content: JSON.stringify(transformed.map) },
|
|
690
|
-
})
|
|
691
|
-
if (!compact.code) this.error('worker minification produced no code')
|
|
692
|
-
if (typeof compact.map !== 'string')
|
|
693
|
-
this.error('worker minification produced no encoded source map')
|
|
694
|
-
return { code: compact.code, map: compact.map }
|
|
824
|
+
// lower vite's final module urls into the shared worker chunk protocol.
|
|
825
|
+
// each chunk retains its own module base rather than the entry's location.
|
|
826
|
+
return renderWorkerSystemChunk(code, chunk.isEntry)
|
|
695
827
|
},
|
|
696
828
|
},
|
|
697
829
|
generateBundle(_options, bundle) {
|
|
698
830
|
if (!isWorker) return
|
|
699
831
|
const chunks = Object.values(bundle).filter((output) => output.type === 'chunk')
|
|
700
|
-
|
|
832
|
+
const entries = chunks.filter((chunk) => chunk.isEntry)
|
|
833
|
+
if (entries.length !== 1) {
|
|
701
834
|
this.error(
|
|
702
|
-
`worker ${closure?.entry ?? 'entry'}: expected one
|
|
835
|
+
`worker ${closure?.entry ?? 'entry'}: expected one boot entry, got ${entries.map((chunk) => chunk.fileName).join(', ')}`,
|
|
703
836
|
)
|
|
704
837
|
}
|
|
705
838
|
// the native host evaluates the same module body in an async strict closure.
|
|
706
839
|
// reject remaining module syntax before it can reach JSContext.
|
|
707
|
-
|
|
840
|
+
for (const chunk of chunks)
|
|
841
|
+
new Script(`(async () => { 'use strict';\n${chunk.code}\n})()`)
|
|
708
842
|
if (!closure) return
|
|
709
|
-
const
|
|
843
|
+
const bootChunk = entries[0]
|
|
844
|
+
const bytes = Buffer.byteLength(bootChunk.code)
|
|
710
845
|
if (bytes > closure.maxBytes) {
|
|
711
|
-
const chunk =
|
|
846
|
+
const chunk = bootChunk
|
|
712
847
|
const pkgs = new Map<string, Set<string>>()
|
|
713
848
|
for (const id of chunk.moduleIds) {
|
|
714
849
|
// a virtual `\0` id (the jsx-runtime re-export shim) names a
|
|
@@ -745,7 +880,7 @@ export function workerBootChunkPlugin(closures: WorkerBootClosure[]): Plugin {
|
|
|
745
880
|
`${module.renderedLength} ${path.relative(process.cwd(), id)}`,
|
|
746
881
|
)
|
|
747
882
|
this.error(
|
|
748
|
-
`worker ${closure.entry}: ${
|
|
883
|
+
`worker ${closure.entry}: ${bootChunk.fileName} is ${bytes} bytes, over the ${closure.maxBytes} byte cap; eliminate excess boot dependencies rather than raising the cap${dupDetail}\nlargest modules (rendered bytes):\n ${largest.join('\n ')}`,
|
|
749
884
|
)
|
|
750
885
|
}
|
|
751
886
|
},
|
|
@@ -1021,10 +1156,12 @@ export function manifestNativeSeamRedirect(): Plugin {
|
|
|
1021
1156
|
}
|
|
1022
1157
|
const targets = new Set(NATIVE_SEAM_MANIFEST.map((entry) => entry.target))
|
|
1023
1158
|
const sourceFilter = new RegExp(
|
|
1024
|
-
`(?:^|/)(?:${[
|
|
1025
|
-
.flatMap((seams) => [...seams.keys()])
|
|
1159
|
+
`(?:^|/)(?:${[
|
|
1160
|
+
...[...byPkg.values()].flatMap((seams) => [...seams.keys()]),
|
|
1161
|
+
...Object.keys(rnLibraryStubs).map((specifier) => path.posix.basename(specifier)),
|
|
1162
|
+
]
|
|
1026
1163
|
.map((basename) => basename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
1027
|
-
.join('|')})(?:\\.(?:native|web|ios|android))?$`,
|
|
1164
|
+
.join('|')})(?:\\.(?:native|web|ios|android))?(?:\\.[cm]?[jt]sx?)?$`,
|
|
1028
1165
|
)
|
|
1029
1166
|
return {
|
|
1030
1167
|
name: 'sootsim-manifest-native-seam-redirect',
|
|
@@ -1032,24 +1169,27 @@ export function manifestNativeSeamRedirect(): Plugin {
|
|
|
1032
1169
|
resolveId: {
|
|
1033
1170
|
filter: { id: sourceFilter },
|
|
1034
1171
|
handler(source, importer) {
|
|
1172
|
+
const nativeLibraryStub = resolveReactNativeLibraryStub(source, importer)
|
|
1173
|
+
if (nativeLibraryStub) return nativeLibraryStub
|
|
1035
1174
|
if (!importer || byPkg.size === 0 || targets.has(importer)) return null
|
|
1036
|
-
// find the package whose path appears in the importer. matches both
|
|
1175
|
+
// find the innermost package whose path appears in the importer. matches both
|
|
1037
1176
|
// `/<pkg>/` (unscoped) and `/@scope/<pkg>/` (scoped — the leading `@`
|
|
1038
1177
|
// is part of the pkg name in the manifest, e.g. `@notifee/react-native`).
|
|
1039
1178
|
let seams: Map<string, { target: string; notes?: string }> | undefined
|
|
1040
1179
|
let matchedPkg: string | undefined
|
|
1180
|
+
let matchedIndex = -1
|
|
1041
1181
|
for (const [pkg, entry] of byPkg) {
|
|
1042
|
-
|
|
1182
|
+
const index = importer.lastIndexOf(`/${pkg}/`)
|
|
1183
|
+
if (index > matchedIndex) {
|
|
1043
1184
|
seams = entry
|
|
1044
1185
|
matchedPkg = pkg
|
|
1045
|
-
|
|
1186
|
+
matchedIndex = index
|
|
1046
1187
|
}
|
|
1047
1188
|
}
|
|
1048
1189
|
if (!seams) return null
|
|
1049
|
-
const basename = (source.split('/').pop() ?? '')
|
|
1050
|
-
/\.
|
|
1051
|
-
''
|
|
1052
|
-
)
|
|
1190
|
+
const basename = (source.split('/').pop() ?? '')
|
|
1191
|
+
.replace(/\.[cm]?[jt]sx?$/, '')
|
|
1192
|
+
.replace(/\.(native|web|ios|android)$/, '')
|
|
1053
1193
|
const seam = seams.get(basename)
|
|
1054
1194
|
if (!seam) return null
|
|
1055
1195
|
if (process.env.SOOTSIM_NATIVE_SEAM_DEBUG) {
|
|
@@ -1070,7 +1210,7 @@ export function manifestNativeSeamRedirect(): Plugin {
|
|
|
1070
1210
|
}
|
|
1071
1211
|
|
|
1072
1212
|
interface ViteBridgeProcessEntry {
|
|
1073
|
-
boundPort: Promise<number
|
|
1213
|
+
boundPort: Promise<number>
|
|
1074
1214
|
close: () => Promise<void>
|
|
1075
1215
|
owners: Set<object>
|
|
1076
1216
|
shellPort: { read: () => number | null }
|
|
@@ -1106,7 +1246,7 @@ export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plug
|
|
|
1106
1246
|
// websocket console error during boot.
|
|
1107
1247
|
// a parent that already owns a bridge supplies its receipt here. the shell
|
|
1108
1248
|
// publishes that exact port and never starts a competing development bridge.
|
|
1109
|
-
let boundPort: Promise<number
|
|
1249
|
+
let boundPort: Promise<number> | null =
|
|
1110
1250
|
options.ownedBridgePort === undefined
|
|
1111
1251
|
? null
|
|
1112
1252
|
: Promise.resolve(options.ownedBridgePort)
|
|
@@ -1122,10 +1262,10 @@ export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plug
|
|
|
1122
1262
|
async closeBundle() {
|
|
1123
1263
|
await releaseBridge?.()
|
|
1124
1264
|
},
|
|
1125
|
-
configureServer(server) {
|
|
1265
|
+
async configureServer(server) {
|
|
1126
1266
|
if (!boundPort) {
|
|
1127
1267
|
const preferredPort = resolveSootsimBridgePort({
|
|
1128
|
-
explicitPort: process.env.
|
|
1268
|
+
explicitPort: process.env.PEACH_BRIDGE_PORT,
|
|
1129
1269
|
portOffset: process.env.PORT_OFFSET,
|
|
1130
1270
|
})
|
|
1131
1271
|
const readShellPort = () => {
|
|
@@ -1141,8 +1281,7 @@ export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plug
|
|
|
1141
1281
|
} else {
|
|
1142
1282
|
// lazy import to avoid pulling ws into the main bundle.
|
|
1143
1283
|
// note: the .ts extension is required on vite 8 / node ESM — without
|
|
1144
|
-
// it, import() throws "Cannot find module"
|
|
1145
|
-
// never starts.
|
|
1284
|
+
// it, import() throws "Cannot find module" before the bridge starts.
|
|
1146
1285
|
const shellPort = { read: readShellPort }
|
|
1147
1286
|
const host = import('./host/bridge-host.ts').then(({ SootSimBridgeHost }) => {
|
|
1148
1287
|
return new SootSimBridgeHost({
|
|
@@ -1154,13 +1293,12 @@ export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plug
|
|
|
1154
1293
|
let entry: ViteBridgeProcessEntry
|
|
1155
1294
|
boundPort = host
|
|
1156
1295
|
.then((bridgeHost) => bridgeHost.startAsync({ silent: true }))
|
|
1157
|
-
.catch((err: unknown) => {
|
|
1296
|
+
.catch(async (err: unknown) => {
|
|
1158
1297
|
if (viteBridgeProcesses.get(preferredPort) === entry) {
|
|
1159
1298
|
viteBridgeProcesses.delete(preferredPort)
|
|
1160
1299
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
return null
|
|
1300
|
+
await entry.close()
|
|
1301
|
+
throw err
|
|
1164
1302
|
})
|
|
1165
1303
|
entry = {
|
|
1166
1304
|
boundPort,
|
|
@@ -1185,31 +1323,27 @@ export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plug
|
|
|
1185
1323
|
}
|
|
1186
1324
|
|
|
1187
1325
|
if (!boundPort) throw new Error('peach bridge identity was not initialized')
|
|
1188
|
-
|
|
1326
|
+
// vite awaits this hook before it can listen. a failed bridge must also
|
|
1327
|
+
// close vite's watchers and transports instead of publishing a ready shell.
|
|
1328
|
+
let bridgePort: number
|
|
1329
|
+
try {
|
|
1330
|
+
bridgePort = await boundPort
|
|
1331
|
+
} catch (err) {
|
|
1332
|
+
await server.close()
|
|
1333
|
+
throw err
|
|
1334
|
+
}
|
|
1189
1335
|
server.middlewares.use((req, res, next) => {
|
|
1190
1336
|
if (req.url?.split('?')[0] !== SHELL_BRIDGE_IDENTITY_PATH) {
|
|
1191
1337
|
next()
|
|
1192
1338
|
return
|
|
1193
1339
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
const identity = {
|
|
1202
|
-
schema: 1,
|
|
1203
|
-
bridgePort,
|
|
1204
|
-
} satisfies ShellBridgeIdentity
|
|
1205
|
-
res.setHeader('Content-Type', 'application/json')
|
|
1206
|
-
res.setHeader('Cache-Control', 'no-store')
|
|
1207
|
-
res.end(JSON.stringify(identity))
|
|
1208
|
-
})
|
|
1209
|
-
.catch(() => {
|
|
1210
|
-
res.statusCode = 503
|
|
1211
|
-
res.end('peach bridge unavailable')
|
|
1212
|
-
})
|
|
1340
|
+
const identity = {
|
|
1341
|
+
schema: 1,
|
|
1342
|
+
bridgePort,
|
|
1343
|
+
} satisfies ShellBridgeIdentity
|
|
1344
|
+
res.setHeader('Content-Type', 'application/json')
|
|
1345
|
+
res.setHeader('Cache-Control', 'no-store')
|
|
1346
|
+
res.end(JSON.stringify(identity))
|
|
1213
1347
|
})
|
|
1214
1348
|
},
|
|
1215
1349
|
// publish the bound port to the page. head-prepend so it lands before the
|
|
@@ -1274,7 +1408,13 @@ function sootsimConfigPlugin(
|
|
|
1274
1408
|
}),
|
|
1275
1409
|
)
|
|
1276
1410
|
|
|
1277
|
-
const dedupe = [
|
|
1411
|
+
const dedupe = [
|
|
1412
|
+
'react',
|
|
1413
|
+
'react-dom',
|
|
1414
|
+
'react/jsx-runtime',
|
|
1415
|
+
'react/jsx-dev-runtime',
|
|
1416
|
+
'expo-asset',
|
|
1417
|
+
]
|
|
1278
1418
|
|
|
1279
1419
|
// internal sootsim builds must keep the entire Tamagui package family on a
|
|
1280
1420
|
// single module graph. mixing raw @fs modules with prebundled .vite/deps
|
|
@@ -1330,10 +1470,18 @@ function sootsimConfigPlugin(
|
|
|
1330
1470
|
'react-dom',
|
|
1331
1471
|
'react-dom/client',
|
|
1332
1472
|
'react-reconciler',
|
|
1333
|
-
'react-reconciler/constants',
|
|
1473
|
+
'react-reconciler/constants.js',
|
|
1334
1474
|
'react/jsx-runtime',
|
|
1335
1475
|
'react/jsx-dev-runtime',
|
|
1336
1476
|
'@react-native/normalize-color',
|
|
1477
|
+
'@react-native/normalize-colors',
|
|
1478
|
+
// these upstream native entries contain CJS even after Flow is stripped.
|
|
1479
|
+
// force interop for workers, whose imports dependency discovery cannot see.
|
|
1480
|
+
'react-native/asset-registry',
|
|
1481
|
+
'@react-native/assets-registry/registry',
|
|
1482
|
+
'@peach-internal/react-native/BatchedBridge/BatchedBridge',
|
|
1483
|
+
'@peach-internal/react-native/Components/View/ReactNativeStyleAttributes',
|
|
1484
|
+
'@peach-internal/react-native/StyleSheet/processColor',
|
|
1337
1485
|
// CJS deps transitively imported by @gorhom/bottom-sheet and
|
|
1338
1486
|
// @gorhom/portal (both excluded above). vite's CJS→ESM interop
|
|
1339
1487
|
// only kicks in via pre-bundle, so these must be pre-bundled even
|
|
@@ -1367,6 +1515,17 @@ function sootsimConfigPlugin(
|
|
|
1367
1515
|
],
|
|
1368
1516
|
},
|
|
1369
1517
|
plugins: [
|
|
1518
|
+
flowStripTransform(),
|
|
1519
|
+
{
|
|
1520
|
+
name: 'peach-react-native-boundaries',
|
|
1521
|
+
resolveId(source: string, importer: string | undefined) {
|
|
1522
|
+
const nativeLibraryStub = resolveReactNativeLibraryStub(
|
|
1523
|
+
source,
|
|
1524
|
+
importer,
|
|
1525
|
+
)
|
|
1526
|
+
return nativeLibraryStub ? { id: nativeLibraryStub } : null
|
|
1527
|
+
},
|
|
1528
|
+
},
|
|
1370
1529
|
{
|
|
1371
1530
|
name: 'sootsim-published-browser-internals',
|
|
1372
1531
|
resolveId(source: string, importer: string | undefined) {
|
|
@@ -1429,8 +1588,31 @@ function sootsimConfigPlugin(
|
|
|
1429
1588
|
find: /^@react-native\/assets-registry\/registry$/,
|
|
1430
1589
|
replacement: rnAssetRegistryPath,
|
|
1431
1590
|
},
|
|
1591
|
+
// upstream virtualized-lists imports this private module by its bare
|
|
1592
|
+
// path, which react-native's exports map hides. load the installed
|
|
1593
|
+
// upstream javascript unchanged, including its native flag getters.
|
|
1594
|
+
{
|
|
1595
|
+
find: /^react-native\/src\/private\/featureflags\/ReactNativeFeatureFlags(?:\.js)?$/,
|
|
1596
|
+
replacement: path.resolve(
|
|
1597
|
+
workspaceNodeModules,
|
|
1598
|
+
'react-native/src/private/featureflags/ReactNativeFeatureFlags.js',
|
|
1599
|
+
),
|
|
1600
|
+
},
|
|
1601
|
+
...[
|
|
1602
|
+
'BatchedBridge/BatchedBridge',
|
|
1603
|
+
'Components/View/ReactNativeStyleAttributes',
|
|
1604
|
+
'StyleSheet/processColor',
|
|
1605
|
+
].map((module) => ({
|
|
1606
|
+
find: `@peach-internal/react-native/${module}`,
|
|
1607
|
+
replacement: path.resolve(
|
|
1608
|
+
workspaceNodeModules,
|
|
1609
|
+
`react-native/Libraries/${module}.js`,
|
|
1610
|
+
),
|
|
1611
|
+
})),
|
|
1432
1612
|
...Object.entries(rnLibraryStubs).map(([find, replacement]) => ({
|
|
1433
|
-
find
|
|
1613
|
+
find: new RegExp(
|
|
1614
|
+
`^${find.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\.[cm]?[jt]sx?)?$`,
|
|
1615
|
+
),
|
|
1434
1616
|
replacement,
|
|
1435
1617
|
})),
|
|
1436
1618
|
{ find: /^react-native\/Libraries\/.*/, replacement: rnDeepStubDefault },
|
|
@@ -1501,6 +1683,7 @@ function reactBridgePlugin(): Plugin {
|
|
|
1501
1683
|
importer.includes('/peachsim/src/') ||
|
|
1502
1684
|
importer.includes('/peach-engine/src/') ||
|
|
1503
1685
|
importer.includes('/peach-compat/src/') ||
|
|
1686
|
+
importer.includes('/peach-compat/dist-pressability/') ||
|
|
1504
1687
|
importer.includes('/peach-kit/src/') ||
|
|
1505
1688
|
importer.includes('react-reconciler')
|
|
1506
1689
|
|
|
@@ -1558,6 +1741,7 @@ export function workerReactBridgePlugin(): Plugin {
|
|
|
1558
1741
|
importer.includes('/peachsim/src/') ||
|
|
1559
1742
|
importer.includes('/peach-engine/src/') ||
|
|
1560
1743
|
importer.includes('/peach-compat/src/') ||
|
|
1744
|
+
importer.includes('/peach-compat/dist-pressability/') ||
|
|
1561
1745
|
importer.includes('/peach-kit/src/') ||
|
|
1562
1746
|
importer.includes('react-reconciler') ||
|
|
1563
1747
|
importer.includes('/node_modules/')
|
|
@@ -1652,6 +1836,10 @@ function sootsimEsbuildPlugin(appDir: string) {
|
|
|
1652
1836
|
return {
|
|
1653
1837
|
name: 'sootsim-esbuild',
|
|
1654
1838
|
setup(build: any) {
|
|
1839
|
+
build.onResolve({ filter: /^(?:\.|\/)/ }, (args: any) => {
|
|
1840
|
+
const nativeLibraryStub = resolveReactNativeLibraryStub(args.path, args.importer)
|
|
1841
|
+
return nativeLibraryStub ? { path: nativeLibraryStub } : null
|
|
1842
|
+
})
|
|
1655
1843
|
// metro-style .ios > .native resolution
|
|
1656
1844
|
build.onResolve({ filter: /^\./ }, (args: any) => {
|
|
1657
1845
|
if (!args.importer.includes('node_modules') && !isAppSourceEsbuild(args.importer))
|
|
@@ -1687,16 +1875,8 @@ function sootsimEsbuildPlugin(appDir: string) {
|
|
|
1687
1875
|
})
|
|
1688
1876
|
|
|
1689
1877
|
// react-native deep path stubs
|
|
1690
|
-
for (const [importPath, stubPath] of Object.entries(rnLibraryStubs)) {
|
|
1691
|
-
build.onResolve(
|
|
1692
|
-
{ filter: new RegExp(`^${importPath.replace(/\//g, '\\/')}$`) },
|
|
1693
|
-
() => ({
|
|
1694
|
-
path: stubPath,
|
|
1695
|
-
}),
|
|
1696
|
-
)
|
|
1697
|
-
}
|
|
1698
1878
|
build.onResolve({ filter: /^react-native\/Libraries\// }, (args: any) => {
|
|
1699
|
-
return { path:
|
|
1879
|
+
return { path: resolveReactNativeLibraryStub(args.path) || rnDeepStubDefault }
|
|
1700
1880
|
})
|
|
1701
1881
|
|
|
1702
1882
|
// resolve builtin stubs (react-native-safe-area-context, expo-*, etc.)
|
|
@@ -1856,13 +2036,13 @@ function loadFlowBabel(): void {
|
|
|
1856
2036
|
'@babel/plugin-syntax-jsx',
|
|
1857
2037
|
) as import('@babel/core').PluginItem
|
|
1858
2038
|
}
|
|
1859
|
-
function flowStripTransform()
|
|
2039
|
+
function flowStripTransform() {
|
|
1860
2040
|
return {
|
|
1861
2041
|
name: 'sootsim-flow-strip',
|
|
1862
2042
|
enforce: 'pre',
|
|
1863
2043
|
transform: {
|
|
1864
2044
|
filter: {
|
|
1865
|
-
id: /\/node_modules\/.*\.[cm]?jsx?$/,
|
|
2045
|
+
id: /\/node_modules\/.*\.[cm]?jsx?(?:\?.*)?$/,
|
|
1866
2046
|
code: /@flow/,
|
|
1867
2047
|
},
|
|
1868
2048
|
handler(code, id) {
|
|
@@ -1879,7 +2059,7 @@ function flowStripTransform(): Plugin {
|
|
|
1879
2059
|
return { code: result.code, map: result.map ?? null }
|
|
1880
2060
|
},
|
|
1881
2061
|
},
|
|
1882
|
-
}
|
|
2062
|
+
} satisfies Plugin
|
|
1883
2063
|
}
|
|
1884
2064
|
|
|
1885
2065
|
function nodeModulesJsxTransform(): Plugin {
|
|
@@ -1888,7 +2068,7 @@ function nodeModulesJsxTransform(): Plugin {
|
|
|
1888
2068
|
enforce: 'pre',
|
|
1889
2069
|
transform: {
|
|
1890
2070
|
filter: {
|
|
1891
|
-
id: /\/node_modules\/.*\.js
|
|
2071
|
+
id: /\/node_modules\/.*\.js(?:\?.*)?$/,
|
|
1892
2072
|
code: /</,
|
|
1893
2073
|
},
|
|
1894
2074
|
async handler(code, id) {
|
|
@@ -2004,7 +2184,8 @@ function reactNativeRequirePlugin(isAppSource: (p: string) => boolean): Plugin {
|
|
|
2004
2184
|
const importPath = match[1]
|
|
2005
2185
|
if (!seenPaths.has(importPath)) {
|
|
2006
2186
|
const varName = `__soot_rn_lib_${importCounter++}__`
|
|
2007
|
-
const stubPath =
|
|
2187
|
+
const stubPath =
|
|
2188
|
+
resolveReactNativeLibraryStub(importPath) || rnDeepStubDefault
|
|
2008
2189
|
imports += `import * as ${varName} from ${JSON.stringify(stubPath)};\n`
|
|
2009
2190
|
seenPaths.set(importPath, varName)
|
|
2010
2191
|
}
|
|
@@ -2064,28 +2245,59 @@ function externalAppResolvePlugin(
|
|
|
2064
2245
|
|
|
2065
2246
|
// convert require() calls and handle JSX in .js files from external app sources
|
|
2066
2247
|
function externalAppTransformPlugin(isAppSource: (p: string) => boolean): Plugin {
|
|
2248
|
+
const defines: Record<string, string> = {}
|
|
2067
2249
|
return {
|
|
2068
2250
|
name: 'sootsim-external-app-transform',
|
|
2069
2251
|
enforce: 'pre',
|
|
2252
|
+
configResolved(config) {
|
|
2253
|
+
for (const [name, value] of Object.entries(config.define ?? {}))
|
|
2254
|
+
defines[name] = typeof value === 'string' ? value : JSON.stringify(value)
|
|
2255
|
+
},
|
|
2070
2256
|
transform: {
|
|
2071
2257
|
filter: { code: /require\(|</ },
|
|
2072
2258
|
async handler(code, id) {
|
|
2073
|
-
|
|
2259
|
+
// expo's winter polyfills use Metro-local requires in lazy getters.
|
|
2260
|
+
// their module imports must never reach the host's native-package registry.
|
|
2261
|
+
if (!isAppSource(id) && !/\/node_modules\/expo\/(?:src|build)\/winter\//.test(id))
|
|
2262
|
+
return null
|
|
2074
2263
|
|
|
2075
|
-
|
|
2264
|
+
// prune upstream's disabled native branches before lifting module imports.
|
|
2265
|
+
let result = /\/node_modules\/expo\/(?:src|build)\/winter\//.test(id)
|
|
2266
|
+
? minifySync(
|
|
2267
|
+
stripViteQuery(id),
|
|
2268
|
+
transformSync(stripViteQuery(id), code, { define: defines }).code,
|
|
2269
|
+
{ mangle: false },
|
|
2270
|
+
).code
|
|
2271
|
+
: code
|
|
2076
2272
|
let imports = ''
|
|
2077
2273
|
let importCounter = 0
|
|
2078
2274
|
let hasChanges = false
|
|
2079
2275
|
|
|
2080
2276
|
if (code.includes('require(')) {
|
|
2081
|
-
const
|
|
2082
|
-
const replacements: Array<{ full: string; varName: string }> = []
|
|
2277
|
+
const replacements: Array<{ start: number; end: number; varName: string }> = []
|
|
2083
2278
|
const seenPaths = new Map<string, string>()
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
const
|
|
2279
|
+
const pending: unknown[] = [parseSync(stripViteQuery(id), result).program]
|
|
2280
|
+
while (pending.length) {
|
|
2281
|
+
const node = pending.pop()
|
|
2282
|
+
if (!isRecord(node)) continue
|
|
2283
|
+
for (const value of Object.values(node)) {
|
|
2284
|
+
if (Array.isArray(value)) pending.push(...value)
|
|
2285
|
+
else if (isRecord(value)) pending.push(value)
|
|
2286
|
+
}
|
|
2287
|
+
if (
|
|
2288
|
+
node.type !== 'CallExpression' ||
|
|
2289
|
+
!isRecord(node.callee) ||
|
|
2290
|
+
node.callee.type !== 'Identifier' ||
|
|
2291
|
+
node.callee.name !== 'require' ||
|
|
2292
|
+
!Array.isArray(node.arguments) ||
|
|
2293
|
+
node.arguments.length !== 1 ||
|
|
2294
|
+
!isRecord(node.arguments[0]) ||
|
|
2295
|
+
typeof node.arguments[0].value !== 'string' ||
|
|
2296
|
+
typeof node.start !== 'number' ||
|
|
2297
|
+
typeof node.end !== 'number'
|
|
2298
|
+
)
|
|
2299
|
+
continue
|
|
2300
|
+
const reqPath = node.arguments[0].value
|
|
2089
2301
|
if (reqPath === 'react-native' || reqPath.startsWith('react-native/'))
|
|
2090
2302
|
continue
|
|
2091
2303
|
|
|
@@ -2094,12 +2306,16 @@ function externalAppTransformPlugin(isAppSource: (p: string) => boolean): Plugin
|
|
|
2094
2306
|
imports += `import * as ${varName} from ${JSON.stringify(reqPath)};\n`
|
|
2095
2307
|
seenPaths.set(reqPath, varName)
|
|
2096
2308
|
}
|
|
2097
|
-
replacements.push({
|
|
2309
|
+
replacements.push({
|
|
2310
|
+
start: node.start,
|
|
2311
|
+
end: node.end,
|
|
2312
|
+
varName: seenPaths.get(reqPath)!,
|
|
2313
|
+
})
|
|
2098
2314
|
}
|
|
2099
2315
|
|
|
2100
2316
|
if (replacements.length > 0) {
|
|
2101
|
-
for (const rep of replacements) {
|
|
2102
|
-
result = result.
|
|
2317
|
+
for (const rep of replacements.sort((a, b) => b.start - a.start)) {
|
|
2318
|
+
result = result.slice(0, rep.start) + rep.varName + result.slice(rep.end)
|
|
2103
2319
|
}
|
|
2104
2320
|
hasChanges = true
|
|
2105
2321
|
}
|
|
@@ -2552,10 +2768,6 @@ export function expoDomComponentsPlugin(
|
|
|
2552
2768
|
if (fs.existsSync(resolved)) {
|
|
2553
2769
|
try {
|
|
2554
2770
|
const stat = fs.statSync(resolved)
|
|
2555
|
-
if (stat.isFile()) {
|
|
2556
|
-
domWebModuleIds.add(resolved)
|
|
2557
|
-
return resolved
|
|
2558
|
-
}
|
|
2559
2771
|
if (stat.isDirectory()) {
|
|
2560
2772
|
const indexCandidates = [
|
|
2561
2773
|
path.join(resolved, 'index.web.tsx'),
|
|
@@ -2596,6 +2808,10 @@ export function expoDomComponentsPlugin(
|
|
|
2596
2808
|
return candidate
|
|
2597
2809
|
}
|
|
2598
2810
|
}
|
|
2811
|
+
if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) {
|
|
2812
|
+
domWebModuleIds.add(resolved)
|
|
2813
|
+
return resolved
|
|
2814
|
+
}
|
|
2599
2815
|
const indexCandidates = [
|
|
2600
2816
|
path.join(resolved, 'index.web.tsx'),
|
|
2601
2817
|
path.join(resolved, 'index.web.ts'),
|