peachsim 0.1.2179 → 0.1.2180
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/cli/commands/package.ts +7 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/bundle-channel.cjs +89 -20
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +2 -2
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +76 -16
- package/dist-lib/expo-swift-metadata.cjs +1 -1
- package/dist-lib/expo-swift-metadata.mjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +100 -28
- package/dist-lib/host/fetch-proxy-handler.cjs +4 -4
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +4 -4
- 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 +11 -3
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +4 -4
- package/dist-lib/native-app-identity-project.cjs +2 -2
- package/dist-lib/native-app-identity-project.mjs +2 -2
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/pdfium-raster.cjs +1 -1
- package/dist-lib/pdfium-raster.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/public-origins-lib-esm.json +24 -24
- package/dist-lib/public-origins-lib.json +53 -53
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/reap-browser.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +113 -114
- package/dist-lib/swift-compile.cjs +74 -14
- package/dist-lib/swift-compile.mjs +74 -14
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +75 -15
- package/dist-lib/vite.cjs +4 -4
- package/dist-lib/worklet-executable.cjs +1 -1
- package/dist-lib/worklet-executable.mjs +1 -1
- package/dist-types/packages/peach-engine/src/cli-companion.d.ts +1 -0
- package/dist-types/packages/peach-engine/src/ios/frame-art.d.ts +41 -0
- package/dist-types/packages/peach-engine/src/ios/frame-paint.d.ts +43 -0
- package/dist-types/packages/peach-engine/src/ios/frame-svg.d.ts +4 -0
- package/kotlin/sdk.tar.gz +0 -0
- package/package.json +1 -1
- package/runtime-companion.json +1 -1
- package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UIScrollView.h +8 -25
- package/sdk/ios/System/Library/Frameworks/UIKitTypes.framework/Headers/UIKitTypes.h +26 -0
- package/src/expo-widgets-bundle.ts +12 -8
- package/src/kotlin-host.ts +10 -2
- package/src/one-sdk-bundle.ts +1 -0
- package/src/screenshots/frame-compose.ts +14 -109
- package/src/swift-compile.ts +102 -12
- package/src/wasm-optimize.ts +2 -3
|
@@ -2363,6 +2363,32 @@ typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
|
|
|
2363
2363
|
UIImageRenderingModeAlwaysOriginal, // Always draw the original image, without treating it as a template
|
|
2364
2364
|
UIImageRenderingModeAlwaysTemplate, // Always draw the image as a template image, ignoring its color information
|
|
2365
2365
|
} API_AVAILABLE(ios(7.0), watchos(2.0));
|
|
2366
|
+
|
|
2367
|
+
typedef NS_ENUM(NSInteger, UIScrollViewIndicatorStyle) {
|
|
2368
|
+
UIScrollViewIndicatorStyleDefault, // Automatically switches appearance based on the user interface style
|
|
2369
|
+
UIScrollViewIndicatorStyleBlack, // Dark indicator, for use on light backgrounds
|
|
2370
|
+
UIScrollViewIndicatorStyleWhite // Light indicator, for use on dark backgrounds
|
|
2371
|
+
} API_UNAVAILABLE(watchos);
|
|
2372
|
+
|
|
2373
|
+
typedef NS_ENUM(NSInteger, UIScrollViewKeyboardDismissMode) {
|
|
2374
|
+
UIScrollViewKeyboardDismissModeNone,
|
|
2375
|
+
UIScrollViewKeyboardDismissModeOnDrag, // dismisses the keyboard when a drag begins
|
|
2376
|
+
UIScrollViewKeyboardDismissModeInteractive, // the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss
|
|
2377
|
+
UIScrollViewKeyboardDismissModeOnDragWithAccessory, // dismisses both keyboard and accessory in the style of UIScrollViewKeyboardDismissModeOnDrag
|
|
2378
|
+
UIScrollViewKeyboardDismissModeInteractiveWithAccessory // dismisses both keyboard and accessory in the style of UIScrollViewKeyboardDismissModeInteractive
|
|
2379
|
+
} API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(visionos, watchos);
|
|
2380
|
+
|
|
2381
|
+
typedef NS_ENUM(NSInteger, UIScrollViewIndexDisplayMode) {
|
|
2382
|
+
UIScrollViewIndexDisplayModeAutomatic, // the index will show or hide automatically as needed
|
|
2383
|
+
UIScrollViewIndexDisplayModeAlwaysHidden, // the index will never be displayed
|
|
2384
|
+
} API_AVAILABLE(tvos(10.2)) API_UNAVAILABLE(watchos);
|
|
2385
|
+
|
|
2386
|
+
typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
|
|
2387
|
+
UIScrollViewContentInsetAdjustmentAutomatic, // Similar to .scrollableAxes, but for backward compatibility will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller, regardless of whether the scroll view is scrollable
|
|
2388
|
+
UIScrollViewContentInsetAdjustmentScrollableAxes, // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)
|
|
2389
|
+
UIScrollViewContentInsetAdjustmentNever, // contentInset is not adjusted
|
|
2390
|
+
UIScrollViewContentInsetAdjustmentAlways, // contentInset is always adjusted by the scroll view's safeAreaInsets
|
|
2391
|
+
} API_AVAILABLE(ios(11.0), tvos(11.0)) API_UNAVAILABLE(watchos);
|
|
2366
2392
|
PEACH_SWIFT_CLASS(UIKitCore) @interface UIColor : NSObject <NSSecureCoding, NSCopying>
|
|
2367
2393
|
@end
|
|
2368
2394
|
|
|
@@ -5,6 +5,7 @@ import path from 'node:path'
|
|
|
5
5
|
import { promisify } from 'node:util'
|
|
6
6
|
import { stageExpoWidgetAssets } from './expo-widget-assets'
|
|
7
7
|
import { compiledModuleRequestHandler } from './nitro-bundle'
|
|
8
|
+
import { withSwiftRootLock } from './swift-root-lock'
|
|
8
9
|
import type { ExpoWidgetExtension } from '../../peach-engine/src/render-worker/expo-widgetContract'
|
|
9
10
|
|
|
10
11
|
export const EXPO_WIDGETS_ROUTE = '/__peach/expo-widgets'
|
|
@@ -29,18 +30,21 @@ export async function buildExpoWidgetsBundle(
|
|
|
29
30
|
// output path. 58 reads an optional platform and output and otherwise writes
|
|
30
31
|
// the same package bundle, so one root argument covers both.
|
|
31
32
|
const packageDir = path.dirname(manifest)
|
|
32
|
-
await
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const runtimeBundle = await withSwiftRootLock(
|
|
34
|
+
path.join(await fs.realpath(packageDir), 'bundle'),
|
|
35
|
+
async () => {
|
|
36
|
+
await promisify(execFile)(
|
|
37
|
+
process.env.NODE_BINARY || 'node',
|
|
38
|
+
[path.join(packageDir, 'scripts/build-bundle.mjs'), appRoot],
|
|
39
|
+
{ cwd: appRoot, maxBuffer: 16 * 1024 * 1024 },
|
|
40
|
+
)
|
|
41
|
+
return fs.readFile(path.join(packageDir, 'bundle/build/ExpoWidgets.bundle'), 'utf8')
|
|
42
|
+
},
|
|
36
43
|
)
|
|
37
44
|
const catalog = await stageExpoWidgetAssets(appRoot, origin)
|
|
38
45
|
return {
|
|
39
46
|
metadata: {
|
|
40
|
-
runtimeBundle
|
|
41
|
-
path.join(packageDir, 'bundle/build/ExpoWidgets.bundle'),
|
|
42
|
-
'utf8',
|
|
43
|
-
),
|
|
47
|
+
runtimeBundle,
|
|
44
48
|
images: catalog?.images ?? {},
|
|
45
49
|
},
|
|
46
50
|
}
|
package/src/kotlin-host.ts
CHANGED
|
@@ -131,7 +131,11 @@ function entrySource(ids: string[]): string {
|
|
|
131
131
|
'',
|
|
132
132
|
'@OptIn(kotlin.js.ExperimentalJsExport::class)',
|
|
133
133
|
'@JsExport',
|
|
134
|
-
'fun
|
|
134
|
+
'fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {',
|
|
135
|
+
' Build.setDevice(model, release, apiLevel)',
|
|
136
|
+
' java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))',
|
|
137
|
+
' java.util.TimeZone.setDevice(timeZone)',
|
|
138
|
+
'}',
|
|
135
139
|
'',
|
|
136
140
|
'@OptIn(kotlin.js.ExperimentalJsExport::class, kotlinx.coroutines.DelicateCoroutinesApi::class)',
|
|
137
141
|
'@JsExport',
|
|
@@ -726,8 +730,12 @@ export async function expoKotlinArtifact(
|
|
|
726
730
|
' ))',
|
|
727
731
|
'}',
|
|
728
732
|
'',
|
|
729
|
-
'@JsExport fun
|
|
733
|
+
'@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {',
|
|
730
734
|
' android.os.Build.setDevice(model, release, apiLevel)',
|
|
735
|
+
' java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))',
|
|
736
|
+
' java.util.TimeZone.setDevice(timeZone)',
|
|
737
|
+
' PeachExpoRuntime.configureProcessLocale(locale)',
|
|
738
|
+
'}',
|
|
731
739
|
'',
|
|
732
740
|
'@JsExport fun peachExpoListen(notify: () -> Unit) {',
|
|
733
741
|
' registered',
|
package/src/one-sdk-bundle.ts
CHANGED
|
@@ -92,6 +92,7 @@ let package = Package(name: "OneSDKGuest", targets: [
|
|
|
92
92
|
)
|
|
93
93
|
const project = projectFor(packagePath)
|
|
94
94
|
project.oneModule = false
|
|
95
|
+
project.optimize = true
|
|
95
96
|
const artifact = await artifactFor(project, 'Sources/App/App.swift', moduleRoot)
|
|
96
97
|
const metadata: OneSDKCompilation = {
|
|
97
98
|
url: `${origin}/__peach/swift/${artifact.hash}.wasm`,
|
|
@@ -2,9 +2,8 @@ import { launchProvisionedPlaywright } from '../../cli/drivers/playwright-provis
|
|
|
2
2
|
import { getCliRuntime } from '../cli-runtime.ts'
|
|
3
3
|
import { cornerRadii, type CornerRadii, type DeviceModel } from '../device-catalog.ts'
|
|
4
4
|
import type { HousingLayer } from '#peach-cli-contract/ios/duo-housing'
|
|
5
|
+
import type { FramePaintSpec } from '#peach-cli-contract/ios/frame-paint'
|
|
5
6
|
|
|
6
|
-
const METALLIC_RING_SHADOW =
|
|
7
|
-
'inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121'
|
|
8
7
|
const FRAME_OUTLINE_BLEED = 1
|
|
9
8
|
|
|
10
9
|
type FrameButtonLayout = {
|
|
@@ -40,9 +39,7 @@ export interface FramedScreenshotLayout {
|
|
|
40
39
|
logicalFrameRadius: CornerRadii
|
|
41
40
|
// folding body art, painted before the screen; null draws one black body
|
|
42
41
|
housingLayers: HousingLayer[] | null
|
|
43
|
-
frameBackground: string
|
|
44
42
|
frameOutline: string
|
|
45
|
-
metallicRingShadow: string | null
|
|
46
43
|
buttons: FrameButtonLayout[]
|
|
47
44
|
legacyHomeButton: LegacyHomeButtonLayout | null
|
|
48
45
|
showHomeIndicator: boolean
|
|
@@ -149,17 +146,11 @@ export function getFramedScreenshotLayout(model: DeviceModel): FramedScreenshotL
|
|
|
149
146
|
housingLayers,
|
|
150
147
|
// the housing paints its own body layer, shadow included: its frame box is
|
|
151
148
|
// wider than the body, because the hinge barrel protrudes past the spine.
|
|
152
|
-
frameBackground: isLegacyHardware
|
|
153
|
-
? 'linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)'
|
|
154
|
-
: housingLayers
|
|
155
|
-
? 'transparent'
|
|
156
|
-
: '#000000',
|
|
157
149
|
frameOutline: isLegacyHardware
|
|
158
150
|
? '0 0 0 1px #1f2125'
|
|
159
151
|
: housingLayers
|
|
160
152
|
? 'none'
|
|
161
153
|
: '0 0 0 1px #333',
|
|
162
|
-
metallicRingShadow: isLegacyHardware || housingLayers ? null : METALLIC_RING_SHADOW,
|
|
163
154
|
buttons,
|
|
164
155
|
legacyHomeButton: isLegacyHardware
|
|
165
156
|
? {
|
|
@@ -182,69 +173,22 @@ export function getFramedScreenshotLayout(model: DeviceModel): FramedScreenshotL
|
|
|
182
173
|
}
|
|
183
174
|
}
|
|
184
175
|
|
|
185
|
-
function renderSideButtonHtml(button: FrameButtonLayout): string {
|
|
186
|
-
const isRight = button.side === 'right'
|
|
187
|
-
const isBottom = button.side === 'bottom'
|
|
188
|
-
const horizontal = button.side === 'top' || isBottom
|
|
189
|
-
const clip = horizontal
|
|
190
|
-
? isBottom
|
|
191
|
-
? 'inset(0 -3px -3px -3px)'
|
|
192
|
-
: 'inset(-3px -3px 0 -3px)'
|
|
193
|
-
: isRight
|
|
194
|
-
? 'inset(-3px -3px -3px 0)'
|
|
195
|
-
: 'inset(-3px 0 -3px -3px)'
|
|
196
|
-
return `
|
|
197
|
-
<div
|
|
198
|
-
aria-hidden="true"
|
|
199
|
-
style="
|
|
200
|
-
position:absolute;
|
|
201
|
-
${
|
|
202
|
-
horizontal
|
|
203
|
-
? `left:${button.top}px;${isBottom ? `bottom:-${button.width}px;` : `top:-${button.width}px;`}`
|
|
204
|
-
: `${isRight ? `right:-${button.width}px;` : `left:-${button.width}px;`}top:${button.top}px;`
|
|
205
|
-
}
|
|
206
|
-
width:${horizontal ? button.height : button.width}px;
|
|
207
|
-
height:${horizontal ? button.width : button.height}px;
|
|
208
|
-
background-color:#212121;
|
|
209
|
-
border-top-left-radius:${isRight || isBottom ? 0 : 1.5}px;
|
|
210
|
-
border-bottom-left-radius:${isRight || button.side === 'top' ? 0 : 1.5}px;
|
|
211
|
-
border-top-right-radius:${button.side === 'left' || isBottom ? 0 : 1.5}px;
|
|
212
|
-
border-bottom-right-radius:${button.side === 'left' || button.side === 'top' ? 0 : 1.5}px;
|
|
213
|
-
box-shadow:
|
|
214
|
-
inset 0 0.5px 0 #616161,
|
|
215
|
-
inset 0 -0.5px 0 #3F3F3F,
|
|
216
|
-
${isRight ? 'inset -0.5px 0 0 #3F3F3F,' : 'inset 0.5px 0 0 #3F3F3F,'}
|
|
217
|
-
0 0 0 0.5px #676767,
|
|
218
|
-
0 0 0 1.5px #000;
|
|
219
|
-
clip-path:${clip};
|
|
220
|
-
pointer-events:none;
|
|
221
|
-
z-index:2;
|
|
222
|
-
"
|
|
223
|
-
></div>
|
|
224
|
-
`
|
|
225
|
-
}
|
|
226
|
-
|
|
227
176
|
function renderFrameHtml(
|
|
228
177
|
layout: FramedScreenshotLayout,
|
|
229
178
|
rawImageDataUrl: string,
|
|
230
179
|
): string {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
z-index:10;
|
|
244
|
-
"
|
|
245
|
-
></div>
|
|
246
|
-
`
|
|
247
|
-
: ''
|
|
180
|
+
const painter = getCliRuntime().ios_frame_svg
|
|
181
|
+
const paintSpec = {
|
|
182
|
+
width: layout.logicalFrameWidth,
|
|
183
|
+
height: layout.logicalFrameHeight,
|
|
184
|
+
radii: layout.logicalFrameRadius,
|
|
185
|
+
body: layout.legacyHomeButton ? 'legacy' : layout.housingLayers ? null : 'solid',
|
|
186
|
+
ring: layout.legacyHomeButton || layout.housingLayers ? null : painter.METALLIC_RING,
|
|
187
|
+
buttons: layout.buttons
|
|
188
|
+
.filter((button) => button.height > 0)
|
|
189
|
+
.map((button) => ({ ...button, hover: 0 })),
|
|
190
|
+
home: layout.legacyHomeButton,
|
|
191
|
+
} satisfies FramePaintSpec
|
|
248
192
|
|
|
249
193
|
// the folding body's rail, glass ring, corner art, and hinge barrel. no
|
|
250
194
|
// z-index, so the screen div after it paints on top.
|
|
@@ -252,42 +196,6 @@ function renderFrameHtml(
|
|
|
252
196
|
.map(getCliRuntime().ios_duo_housing.housingLayerHtml)
|
|
253
197
|
.join('')
|
|
254
198
|
|
|
255
|
-
const legacyHomeButtonHtml = layout.legacyHomeButton
|
|
256
|
-
? `
|
|
257
|
-
<div
|
|
258
|
-
aria-hidden="true"
|
|
259
|
-
style="
|
|
260
|
-
position:absolute;
|
|
261
|
-
top:${layout.legacyHomeButton.top}px;
|
|
262
|
-
left:${layout.legacyHomeButton.left}px;
|
|
263
|
-
width:${layout.legacyHomeButton.size}px;
|
|
264
|
-
height:${layout.legacyHomeButton.size}px;
|
|
265
|
-
border-radius:50%;
|
|
266
|
-
background:
|
|
267
|
-
radial-gradient(circle at 35% 32%, rgba(62,64,68,0.35) 0%, rgba(17,18,20,0.98) 72%, rgba(8,9,11,1) 100%);
|
|
268
|
-
box-shadow:
|
|
269
|
-
inset 0 0 0 1px rgba(255,255,255,0.06),
|
|
270
|
-
inset 0 0 0 ${layout.legacyHomeButton.ring}px rgba(184,192,204,0.45),
|
|
271
|
-
0 0 0 1px rgba(0,0,0,0.5);
|
|
272
|
-
z-index:3;
|
|
273
|
-
pointer-events:none;
|
|
274
|
-
display:flex;
|
|
275
|
-
align-items:center;
|
|
276
|
-
justify-content:center;
|
|
277
|
-
"
|
|
278
|
-
>
|
|
279
|
-
<div
|
|
280
|
-
style="
|
|
281
|
-
width:16px;
|
|
282
|
-
height:16px;
|
|
283
|
-
border-radius:4px;
|
|
284
|
-
box-shadow:inset 0 0 0 1.5px rgba(188,194,202,0.5);
|
|
285
|
-
"
|
|
286
|
-
></div>
|
|
287
|
-
</div>
|
|
288
|
-
`
|
|
289
|
-
: ''
|
|
290
|
-
|
|
291
199
|
const homeIndicatorHtml = layout.showHomeIndicator
|
|
292
200
|
? `
|
|
293
201
|
<div
|
|
@@ -374,14 +282,11 @@ function renderFrameHtml(
|
|
|
374
282
|
border-radius:${layout.housingLayers ? '0' : getCliRuntime().settings_devices.formatCornerRadii(layout.logicalFrameRadius)};
|
|
375
283
|
box-sizing:border-box;
|
|
376
284
|
overflow:visible;
|
|
377
|
-
background:${layout.frameBackground};
|
|
378
285
|
box-shadow:${layout.frameOutline};
|
|
379
286
|
"
|
|
380
287
|
>
|
|
381
|
-
${
|
|
382
|
-
${ringHtml}
|
|
288
|
+
${painter.frameSvg(paintSpec)}
|
|
383
289
|
${housingHtml}
|
|
384
|
-
${legacyHomeButtonHtml}
|
|
385
290
|
<div
|
|
386
291
|
id="screen"
|
|
387
292
|
style="
|
package/src/swift-compile.ts
CHANGED
|
@@ -1791,6 +1791,32 @@ export function emitSwiftPackageManifest(args: {
|
|
|
1791
1791
|
const linkedObjects = Boolean(distribution || prebuilt)
|
|
1792
1792
|
const cxxFlagsFor = (flags: readonly string[]): readonly string[] =>
|
|
1793
1793
|
args.deferDarwinOverlay ? withoutWasmOverlayIsystem(flags) : flags
|
|
1794
|
+
// swiftpm writes the module map of a target with no swift sources, so an
|
|
1795
|
+
// installed pod's map of that module (a prebuilt React Native core target
|
|
1796
|
+
// the app's pods also list) would define it twice. a swift target imports
|
|
1797
|
+
// its underlying objective-c module through the pod's map and keeps it.
|
|
1798
|
+
const packageModules = new Set(
|
|
1799
|
+
targets
|
|
1800
|
+
.filter(({ name }) => !args.sourceSwiftTargets?.has(name))
|
|
1801
|
+
.map(({ name }) => swiftTargetModuleName(name)),
|
|
1802
|
+
)
|
|
1803
|
+
const mapsPackageModule = (flag: string): boolean => {
|
|
1804
|
+
if (!flag.startsWith('-fmodule-map-file=')) return false
|
|
1805
|
+
const file = flag
|
|
1806
|
+
.slice('-fmodule-map-file='.length)
|
|
1807
|
+
.replaceAll(SWIFT_NATIVE_INPUT_ROOT, args.root)
|
|
1808
|
+
if (!file.includes('/Pods/Headers/')) return false
|
|
1809
|
+
const map =
|
|
1810
|
+
args.files.get(file) ?? (existsSync(file) ? readFileSync(file) : undefined)
|
|
1811
|
+
const name = map === undefined ? undefined : moduleMapName(map.toString())
|
|
1812
|
+
return name !== undefined && packageModules.has(name)
|
|
1813
|
+
}
|
|
1814
|
+
const withoutPackageModuleMaps = (flags: readonly string[]): string[] =>
|
|
1815
|
+
flags.filter((flag) => !mapsPackageModule(flag))
|
|
1816
|
+
const targetCFlags = (flags: readonly string[]) =>
|
|
1817
|
+
cFlagArray(withoutPackageModuleMaps(flags))
|
|
1818
|
+
const targetCxxFlags = (flags: readonly string[]) =>
|
|
1819
|
+
cxxFlagArray(withoutPackageModuleMaps(flags))
|
|
1794
1820
|
const reachedFrameworks = new Set<string>()
|
|
1795
1821
|
const reach = (name: string) => {
|
|
1796
1822
|
if (
|
|
@@ -1908,7 +1934,11 @@ export function emitSwiftPackageManifest(args: {
|
|
|
1908
1934
|
// swiftpm expands target settings into one command; large native import
|
|
1909
1935
|
// closures exceed exec's argument limit. keep their ordered bytes on disk.
|
|
1910
1936
|
const swiftFlagArray = (literal: string): string => {
|
|
1911
|
-
const flags: string[] = JSON.parse(literal.replace(/,\s*]$/, ']'))
|
|
1937
|
+
const flags: string[] = JSON.parse(literal.replace(/,\s*]$/, ']')).filter(
|
|
1938
|
+
(flag: string, index: number, all: string[]) =>
|
|
1939
|
+
!mapsPackageModule(flag) &&
|
|
1940
|
+
!(flag === '-Xcc' && mapsPackageModule(all[index + 1] ?? '')),
|
|
1941
|
+
)
|
|
1912
1942
|
const content = flags.map((flag) => JSON.stringify(flag)).join('\n') + '\n'
|
|
1913
1943
|
const digest = createHash('sha256').update(content).digest('hex')
|
|
1914
1944
|
const file = path.join(args.root, '.peach-swift-arguments', `${digest}.rsp`)
|
|
@@ -2182,7 +2212,7 @@ export function emitSwiftPackageManifest(args: {
|
|
|
2182
2212
|
.map((entry) => ` ${entry},`)
|
|
2183
2213
|
.join(
|
|
2184
2214
|
'',
|
|
2185
|
-
)} .unsafeFlags(${flagArray(
|
|
2215
|
+
)} .unsafeFlags(${flagArray(targetCFlags([...nativeFlags, ...native.clang.flags]))})]`,
|
|
2186
2216
|
...(nativeCxx
|
|
2187
2217
|
? [
|
|
2188
2218
|
`cxxSettings: [${cxxDefines}${clangSettingEntries(
|
|
@@ -2192,13 +2222,13 @@ export function emitSwiftPackageManifest(args: {
|
|
|
2192
2222
|
.map((entry) => ` ${entry},`)
|
|
2193
2223
|
.join(
|
|
2194
2224
|
'',
|
|
2195
|
-
)} .unsafeFlags(${flagArray(
|
|
2225
|
+
)} .unsafeFlags(${flagArray(targetCxxFlags([...cxxFlagsFor(nativeFlags), ...native.clang.cxxFlags]))})]`,
|
|
2196
2226
|
]
|
|
2197
2227
|
: []),
|
|
2198
2228
|
].join(', ')
|
|
2199
2229
|
: [
|
|
2200
|
-
`cSettings: [${cDefines}${declaredClangSettings(target, 'c')} .unsafeFlags(${flagArray(
|
|
2201
|
-
`cxxSettings: [${cxxDefines}${declaredClangSettings(target, 'cxx')} .unsafeFlags(${flagArray(
|
|
2230
|
+
`cSettings: [${cDefines}${declaredClangSettings(target, 'c')} .unsafeFlags(${flagArray(targetCFlags([...nativeFlags, ...(native?.flags ?? [])]))})]`,
|
|
2231
|
+
`cxxSettings: [${cxxDefines}${declaredClangSettings(target, 'cxx')} .unsafeFlags(${flagArray(targetCxxFlags([...cxxFlagsFor(nativeFlags), ...(native?.cxxFlags ?? [])]))})]`,
|
|
2202
2232
|
].join(', ')
|
|
2203
2233
|
const exclusions = native?.clang
|
|
2204
2234
|
? []
|
|
@@ -2287,10 +2317,10 @@ export function emitSwiftPackageManifest(args: {
|
|
|
2287
2317
|
` path: ${JSON.stringify(group.path)},`,
|
|
2288
2318
|
` sources: ${JSON.stringify(group.sources)},`,
|
|
2289
2319
|
` publicHeadersPath: ${JSON.stringify(native.groups ? 'include' : 'PeachSwiftImplementation')},`,
|
|
2290
|
-
` cSettings: [${macroSettings(owner?.cDefines)}${declaredClangSettings(owner, 'c')} .unsafeFlags(${flagArray(
|
|
2320
|
+
` cSettings: [${macroSettings(owner?.cDefines)}${declaredClangSettings(owner, 'c')} .unsafeFlags(${flagArray(targetCFlags([...nativeFlags, '-I', native.includeDirectory, ...(args.headerDirectory ? ['-I', args.headerDirectory] : []), ...group.flags]))})],`,
|
|
2291
2321
|
...(group.sources.some((source) => /\.(?:cc|cpp|cxx|mm)$/.test(source))
|
|
2292
2322
|
? [
|
|
2293
|
-
` cxxSettings: [${macroSettings(owner?.cxxDefines)}${declaredClangSettings(owner, 'cxx')} .unsafeFlags(${flagArray(
|
|
2323
|
+
` cxxSettings: [${macroSettings(owner?.cxxDefines)}${declaredClangSettings(owner, 'cxx')} .unsafeFlags(${flagArray(targetCxxFlags([...cxxFlagsFor(nativeFlags), '-I', native.includeDirectory, ...group.cxxFlags]))})]),`,
|
|
2294
2324
|
]
|
|
2295
2325
|
: [' ),']),
|
|
2296
2326
|
])
|
|
@@ -4300,7 +4330,11 @@ export function writeSwiftProject(
|
|
|
4300
4330
|
const target = bySourcePath.find(
|
|
4301
4331
|
(candidate) => candidate.path === '.' || file.startsWith(`${candidate.path}/`),
|
|
4302
4332
|
)
|
|
4303
|
-
|
|
4333
|
+
// swiftpm never compiles an excluded file (a prebuilt core's Swift)
|
|
4334
|
+
const excluded = target?.exclude?.some(
|
|
4335
|
+
(name) => file === path.posix.join(target.path, name),
|
|
4336
|
+
)
|
|
4337
|
+
if (target && !excluded) swiftTargets.add(target.name)
|
|
4304
4338
|
}
|
|
4305
4339
|
// swiftpm builds a clang target's module only for an importer: a swift
|
|
4306
4340
|
// import, or a framework-style include or @import in any original source.
|
|
@@ -5650,6 +5684,9 @@ export function writeSwiftProject(
|
|
|
5650
5684
|
frameworkLink,
|
|
5651
5685
|
[
|
|
5652
5686
|
...prebuilt.objects.map(quote),
|
|
5687
|
+
'-Wl,--start-lib',
|
|
5688
|
+
...prebuilt.lazyObjects.map(quote),
|
|
5689
|
+
'-Wl,--end-lib',
|
|
5653
5690
|
...darwinRecordsRegion(prebuilt.providers.map(quote)),
|
|
5654
5691
|
].join('\n') + '\n',
|
|
5655
5692
|
)
|
|
@@ -6178,7 +6215,15 @@ function linkedFrameworkTargets(
|
|
|
6178
6215
|
)
|
|
6179
6216
|
const targets = compileTargets(input)
|
|
6180
6217
|
const planning = targets.length > 0 ? targets : [{ name: 'App', path: '.' }]
|
|
6181
|
-
|
|
6218
|
+
// a target's prebuilt library links the units its package excludes from
|
|
6219
|
+
// compilation (a React Native core), so their imports reach frameworks too
|
|
6220
|
+
const siblings = swiftTargetDependencies(
|
|
6221
|
+
input.files,
|
|
6222
|
+
planning.map((target) =>
|
|
6223
|
+
input.libraries?.[target.name] ? { ...target, exclude: [] } : target,
|
|
6224
|
+
),
|
|
6225
|
+
libraries.keys(),
|
|
6226
|
+
)
|
|
6182
6227
|
const reached = new Set<string>()
|
|
6183
6228
|
const reach = (name: string) => {
|
|
6184
6229
|
if (name === 'SwiftUI') return
|
|
@@ -6409,8 +6454,13 @@ function removeCaseCollidingModuleArtifacts(
|
|
|
6409
6454
|
|
|
6410
6455
|
/** a source checkout's framework build: what the app link reads from it. */
|
|
6411
6456
|
interface SwiftFrameworkProducts {
|
|
6457
|
+
/** the distribution-shaped root whose lib/ holds the framework objects */
|
|
6458
|
+
root: string
|
|
6412
6459
|
modules: string
|
|
6460
|
+
/** objects the link loads whole */
|
|
6413
6461
|
objects: string[]
|
|
6462
|
+
/** objects the link loads only for a symbol it resolves */
|
|
6463
|
+
lazyObjects: string[]
|
|
6414
6464
|
owners: Map<string, string>
|
|
6415
6465
|
/** the Darwin module's providers, linked as an archive ahead of the sdk's */
|
|
6416
6466
|
providers: string[]
|
|
@@ -6572,9 +6622,41 @@ async function buildFrameworkProducts(
|
|
|
6572
6622
|
.sort()
|
|
6573
6623
|
.map((file) => path.join(providerDir, file))
|
|
6574
6624
|
for (const provider of providers) linked.owners.set(provider, 'DarwinRecords')
|
|
6625
|
+
// the framework objects link as a distribution's do: under lib/ with the names
|
|
6626
|
+
// build-distribution.ts gives them, Objective-C roots whole and the rest as an
|
|
6627
|
+
// archive region the pruner trims (swift-wasm-prune.ts reads <root>/lib).
|
|
6628
|
+
// Darwin stays whole: a distribution leaves it to the sdk's image.
|
|
6629
|
+
const archive = path.join(scratch, 'lib')
|
|
6630
|
+
rmSync(archive, { recursive: true, force: true })
|
|
6631
|
+
mkdirSync(archive)
|
|
6632
|
+
const archived = new Map<string, string>()
|
|
6633
|
+
for (const object of objects) {
|
|
6634
|
+
const target = linked.owners.get(object)
|
|
6635
|
+
const dir = path.join(release, `${target}.build`)
|
|
6636
|
+
if (!target || target === 'Darwin' || !object.startsWith(dir + path.sep)) continue
|
|
6637
|
+
const name = `${target}-${path
|
|
6638
|
+
.relative(dir, object)
|
|
6639
|
+
.replaceAll(path.sep, '-')
|
|
6640
|
+
.replace(/\.swift\.o$/, '.o')}`
|
|
6641
|
+
symlinkSync(object, path.join(archive, name))
|
|
6642
|
+
archived.set(object, `lib/${name}`)
|
|
6643
|
+
}
|
|
6644
|
+
const roots = swiftObjcRootObjects(`${scratch}\n${args.frameworkKey}`, scratch, [
|
|
6645
|
+
...archived.values(),
|
|
6646
|
+
])
|
|
6647
|
+
const linkedObjects = objects.map((object) => {
|
|
6648
|
+
const name = archived.get(object)
|
|
6649
|
+
return name
|
|
6650
|
+
? { path: path.join(scratch, name), lazy: !roots.has(name) }
|
|
6651
|
+
: { path: object, lazy: false }
|
|
6652
|
+
})
|
|
6575
6653
|
return {
|
|
6654
|
+
root: scratch,
|
|
6576
6655
|
modules: path.join(release, 'Modules'),
|
|
6577
|
-
objects,
|
|
6656
|
+
objects: linkedObjects.filter((object) => !object.lazy).map((object) => object.path),
|
|
6657
|
+
lazyObjects: linkedObjects
|
|
6658
|
+
.filter((object) => object.lazy)
|
|
6659
|
+
.map((object) => object.path),
|
|
6578
6660
|
owners: linked.owners,
|
|
6579
6661
|
providers,
|
|
6580
6662
|
link,
|
|
@@ -6788,6 +6870,8 @@ function swiftLinkStamp(args: {
|
|
|
6788
6870
|
}
|
|
6789
6871
|
for (const object of args.prebuilt.objects)
|
|
6790
6872
|
hash.update(`object\n${object}\n${statOf(object)}`)
|
|
6873
|
+
for (const object of args.prebuilt.lazyObjects)
|
|
6874
|
+
hash.update(`lazy-object\n${object}\n${statOf(object)}`)
|
|
6791
6875
|
for (const object of args.prebuilt.providers)
|
|
6792
6876
|
hash.update(`provider\n${object}\n${statOf(object)}`)
|
|
6793
6877
|
for (const map of args.prebuilt.moduleMaps)
|
|
@@ -7302,7 +7386,7 @@ function compileSwiftProjectOnce(
|
|
|
7302
7386
|
pruneSwiftWasmLink(
|
|
7303
7387
|
root,
|
|
7304
7388
|
options.toolchainBin,
|
|
7305
|
-
frameworkRoot,
|
|
7389
|
+
prebuilt?.root ?? frameworkRoot,
|
|
7306
7390
|
input.staticClangTargets,
|
|
7307
7391
|
options.project,
|
|
7308
7392
|
undefined,
|
|
@@ -7328,9 +7412,15 @@ function compileSwiftProjectOnce(
|
|
|
7328
7412
|
optimized,
|
|
7329
7413
|
})
|
|
7330
7414
|
else if (input.optimize) await optimizeWasm(output, optimized)
|
|
7415
|
+
const executable = input.optimize ? optimized : output
|
|
7416
|
+
await runCompiler(
|
|
7417
|
+
path.join(options.toolchainBin, 'llvm-objcopy'),
|
|
7418
|
+
['--remove-section=.swift1_autolink_entries', executable],
|
|
7419
|
+
buildOptions,
|
|
7420
|
+
)
|
|
7331
7421
|
const artifact = {
|
|
7332
7422
|
hash,
|
|
7333
|
-
bytes: readFileSync(
|
|
7423
|
+
bytes: readFileSync(executable),
|
|
7334
7424
|
icu: await icu,
|
|
7335
7425
|
}
|
|
7336
7426
|
if (!options.project) saveCompiledArtifact(root, artifact)
|
package/src/wasm-optimize.ts
CHANGED
|
@@ -4,11 +4,10 @@ import { installVerifiedTarball } from '@contrast/runtime-delivery'
|
|
|
4
4
|
import { BINARYEN_VERSION, wasmOpt } from 'wasm-opt'
|
|
5
5
|
import { rnxHomeDir } from './home-paths'
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// packaged native executables, size-optimized. clang's own
|
|
8
8
|
// optimizer pass is off (-O0 on the link) so an edit never pays for it and the
|
|
9
9
|
// artifact never depends on the machine; this runs the pinned Binaryen once per
|
|
10
|
-
// cached artifact instead. the features are the ones the link declares
|
|
11
|
-
// pass drops the custom sections (autolink entries, producers) no host reads.
|
|
10
|
+
// cached artifact instead. the features are the ones the link declares.
|
|
12
11
|
const FEATURES = [
|
|
13
12
|
'threads',
|
|
14
13
|
'bulk-memory',
|