peachsim 0.1.1620 → 0.1.1635

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.
Files changed (185) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +45 -6
  3. package/cli/app-config.ts +4 -1
  4. package/cli/app-fonts.ts +39 -18
  5. package/cli/app-stubs.ts +224 -9
  6. package/cli/bridge-flow-runner.ts +248 -156
  7. package/cli/cloud-client.ts +68 -57
  8. package/cli/command-registry.ts +1 -0
  9. package/cli/commands/box/search-command.ts +3 -2
  10. package/cli/commands/box.ts +10 -29
  11. package/cli/commands/control.ts +391 -92
  12. package/cli/commands/doctor.ts +17 -184
  13. package/cli/commands/flow.ts +79 -11
  14. package/cli/commands/inspect/core.ts +10 -5
  15. package/cli/commands/inspect/settling.ts +71 -22
  16. package/cli/commands/inspect/wait-ready.ts +12 -0
  17. package/cli/commands/inspect.ts +26 -3
  18. package/cli/commands/install-desktop.ts +1 -0
  19. package/cli/commands/maestro-compare.ts +105 -67
  20. package/cli/commands/maestro.ts +9 -1
  21. package/cli/commands/platform.ts +71 -36
  22. package/cli/commands/record.ts +21 -1
  23. package/cli/commands/screenshot.ts +23 -1
  24. package/cli/commands/serve.ts +7 -2
  25. package/cli/commands/setup.ts +19 -42
  26. package/cli/commands/swift.ts +5 -0
  27. package/cli/commands/upload.ts +51 -8
  28. package/cli/desktop-companion.ts +102 -17
  29. package/cli/dev-build-freshness.ts +37 -2
  30. package/cli/drivers/desktop.ts +14 -1
  31. package/cli/drivers/playwright-sim-host.ts +44 -8
  32. package/cli/drivers/playwright.ts +9 -8
  33. package/cli/drivers/types.ts +5 -0
  34. package/cli/maestro-accessibility.ts +53 -0
  35. package/cli/maestro-compare.ts +108 -12
  36. package/cli/main.ts +2 -1
  37. package/cli/outbound-endpoints.ts +35 -6
  38. package/cli/parent-pid.ts +0 -9
  39. package/cli/pause-aware-timeout.ts +102 -0
  40. package/cli/remote-simulators.ts +112 -0
  41. package/cli/remoteSimulatorContract.ts +21 -0
  42. package/cli/scene-video.ts +89 -0
  43. package/cli/ws-bridge.ts +23 -14
  44. package/detox/attempt-events.cjs +4 -0
  45. package/detox/expectations.ts +5 -1
  46. package/detox/index.ts +241 -181
  47. package/detox/motion-change.cjs +73 -0
  48. package/detox/motion-change.d.cts +21 -0
  49. package/detox/navigation-lifecycle.ts +22 -4
  50. package/dist-lib/agent-daemon-client.cjs +3 -2
  51. package/dist-lib/agent-events.cjs +1 -1
  52. package/dist-lib/attached-projects.cjs +1 -1
  53. package/dist-lib/auth/shared-session.cjs +3 -2
  54. package/dist-lib/backend-origin.cjs +1 -1
  55. package/dist-lib/beta.cjs +1 -1
  56. package/dist-lib/beta.mjs +1 -1
  57. package/dist-lib/bridge-constants.cjs +13 -1
  58. package/dist-lib/bridge-contract-input.cjs +1 -1
  59. package/dist-lib/bridge-contract-input.mjs +1 -1
  60. package/dist-lib/bridge-contract.cjs +14 -8
  61. package/dist-lib/bridge-contract.mjs +13 -7
  62. package/dist-lib/bundle-channel.cjs +10480 -7962
  63. package/dist-lib/capture-contract.cjs +1 -1
  64. package/dist-lib/capture-contract.mjs +1 -1
  65. package/dist-lib/cloud-contract.cjs +1 -1
  66. package/dist-lib/cloud-contract.mjs +1 -1
  67. package/dist-lib/cloud-test-args.cjs +1 -1
  68. package/dist-lib/cloud-test-args.mjs +1 -1
  69. package/dist-lib/cloud.cjs +3 -2
  70. package/dist-lib/cloud.mjs +3 -2
  71. package/dist-lib/config.cjs +10 -6
  72. package/dist-lib/config.mjs +10 -6
  73. package/dist-lib/detox/index.cjs +1854 -966
  74. package/dist-lib/dev-bundle-resolution.cjs +64 -24
  75. package/dist-lib/expo-swift-bundle.cjs +8715 -6271
  76. package/dist-lib/expo-swift-metadata.cjs +7 -4
  77. package/dist-lib/expo-swift-metadata.mjs +7 -4
  78. package/dist-lib/home-paths.cjs +32 -3
  79. package/dist-lib/host/bridge-host.cjs +10135 -7060
  80. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  81. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  82. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  83. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  84. package/dist-lib/host/websocket-proxy.cjs +1 -1
  85. package/dist-lib/index.cjs +1843 -408
  86. package/dist-lib/jump-to-source-babel.cjs +1 -1
  87. package/dist-lib/jump-to-source-native.cjs +1 -1
  88. package/dist-lib/kotlin-host.cjs +1 -1
  89. package/dist-lib/menu.cjs +3 -2
  90. package/dist-lib/menu.mjs +3 -2
  91. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  92. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  93. package/dist-lib/metro-production-bundle.cjs +5 -4
  94. package/dist-lib/metro-production-bundle.mjs +5 -4
  95. package/dist-lib/metro.cjs +1182 -418
  96. package/dist-lib/native-app-identity-project.cjs +782 -23
  97. package/dist-lib/native-app-identity-project.mjs +781 -23
  98. package/dist-lib/native-app-identity.cjs +276 -9
  99. package/dist-lib/native-app-identity.mjs +273 -8
  100. package/dist-lib/native-firebase-metadata.cjs +5 -4
  101. package/dist-lib/native-firebase-metadata.mjs +5 -4
  102. package/dist-lib/plist.cjs +1 -1
  103. package/dist-lib/plist.mjs +1 -1
  104. package/dist-lib/profiles.cjs +1 -1
  105. package/dist-lib/public-brand.cjs +3 -2
  106. package/dist-lib/react-native-host-modules.cjs +8 -1
  107. package/dist-lib/react-native-host-modules.mjs +8 -1
  108. package/dist-lib/scripts/dev-server-scanner.cjs +106 -28
  109. package/dist-lib/sdk.cjs +115 -34
  110. package/dist-lib/sdk.mjs +115 -33
  111. package/dist-lib/skills.cjs +15274 -9904
  112. package/dist-lib/swift-compile.cjs +1165 -173
  113. package/dist-lib/swift-compile.mjs +1212 -203
  114. package/dist-lib/swift-package.cjs +12 -3
  115. package/dist-lib/swift-package.mjs +12 -3
  116. package/dist-lib/swift-submit.cjs +7 -1
  117. package/dist-lib/swift-submit.mjs +5 -1
  118. package/dist-lib/swift-toolchain.cjs +133 -18
  119. package/dist-lib/swift.cjs +1 -1
  120. package/dist-lib/vite-swift.cjs +2648 -862
  121. package/dist-lib/vite.cjs +70 -14
  122. package/dist-lib/worklet-executable.cjs +25 -2
  123. package/dist-lib/worklet-executable.mjs +25 -2
  124. package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
  125. package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
  126. package/package.json +2 -2
  127. package/scripts/dev-server-scanner.ts +35 -14
  128. package/skills/peach-perf/SKILL.md +11 -5
  129. package/skills/peach-setup/SKILL.md +16 -19
  130. package/src/admitted-mac-build.ts +34 -8
  131. package/src/android-app-identity.ts +146 -0
  132. package/src/android-autolinking.ts +75 -0
  133. package/src/android-string-value.ts +36 -0
  134. package/src/android-strings.ts +5 -36
  135. package/src/androidAutolinkingContract.ts +40 -0
  136. package/src/bridge-constants.ts +11 -0
  137. package/src/bridge-contract.ts +22 -34
  138. package/src/bundleGlobalFooter.ts +26 -7
  139. package/src/codex-client.ts +3 -2
  140. package/src/config.ts +15 -0
  141. package/src/desktop-host-delivery.ts +5 -1
  142. package/src/dev-bundle-resolution.ts +60 -26
  143. package/src/expo-kotlin-host.ts +6 -36
  144. package/src/expo-manifest-body.ts +13 -0
  145. package/src/expo-swift-bundle.ts +17 -12
  146. package/src/expo-swift-host.ts +640 -192
  147. package/src/expo-swift-ready.ts +78 -0
  148. package/src/expoSwiftContract.ts +19 -0
  149. package/src/home-paths.ts +48 -2
  150. package/src/host/bridge-host.ts +12 -57
  151. package/src/host/staged-host-files.ts +29 -2
  152. package/src/installed-package-versions.ts +54 -14
  153. package/src/launchMetadataContract.ts +24 -0
  154. package/src/metro-plugin.ts +37 -42
  155. package/src/native-app-identity-project.ts +142 -5
  156. package/src/native-app-identity.ts +176 -11
  157. package/src/native-firebase-config.ts +209 -13
  158. package/src/nitro-compile.ts +2 -5
  159. package/src/nitro-source.ts +147 -63
  160. package/src/process-group.ts +114 -61
  161. package/src/process-output.ts +0 -9
  162. package/src/public-brand.ts +1 -0
  163. package/src/react-native-bridge-modules.ts +416 -0
  164. package/src/react-native-host-modules.ts +7 -0
  165. package/src/sim-client.ts +6 -4
  166. package/src/swift-binary-modules.ts +2 -2
  167. package/src/swift-compile.ts +1007 -108
  168. package/src/swift-compiler-digest.ts +14 -0
  169. package/src/swift-distribution.lock.json +40 -12
  170. package/src/swift-distribution.ts +61 -9
  171. package/src/swift-host.ts +149 -56
  172. package/src/swift-icu.ts +14 -6
  173. package/src/swift-objc-sdk.ts +133 -10
  174. package/src/swift-objc-standin.ts +38 -3
  175. package/src/swift-package-manifest.ts +21 -6
  176. package/src/swift-package.ts +15 -1
  177. package/src/swift-packages.ts +119 -60
  178. package/src/swift-standin-emit.ts +57 -9
  179. package/src/swift-standins.ts +185 -25
  180. package/src/swift-submit.ts +10 -0
  181. package/src/swift-toolchain.ts +149 -23
  182. package/src/vite-plugin.ts +20 -20
  183. package/src/worklet-executable.ts +30 -3
  184. package/src/worklets-babel.ts +35 -14
  185. package/src/xcode-project.ts +10 -0
@@ -17,6 +17,7 @@ import { fileURLToPath, pathToFileURL } from 'url'
17
17
  import { parseSync } from 'oxc-parser'
18
18
  import { minifySync, transformSync } from 'rolldown/utils'
19
19
  import { type Plugin, transformWithOxc } from 'vite'
20
+ import { resolveOneNativeBackend } from '../../contrast-bundler/src/oneFramework.ts'
20
21
  import { transformFlowSource } from '../../peach-compat/src/flow-strip.ts'
21
22
  import { renderWorkerSystemChunk } from './worker-system-chunks.ts'
22
23
 
@@ -34,7 +35,7 @@ import {
34
35
  import { resolveExportsHiddenSubpath } from '../../peach-compat/src/resolve-hidden-subpath.ts'
35
36
  import {
36
37
  SOOTSIM_COMPAT_PUBLISHED_BROWSER_ENTRIES,
37
- SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES,
38
+ PEACH_UPSTREAM_MODULES,
38
39
  SOOTSIM_HAPTIC_FEEDBACK_TOUCHABLE_SOURCE,
39
40
  SOOTSIM_HAPTIC_FEEDBACK_TOUCHABLE_SPECIFIER,
40
41
  compatStubsForBuildResolver,
@@ -46,7 +47,10 @@ import {
46
47
  isReactNativeEnvironmentSetupModule,
47
48
  } from '../../peach-engine/src/guest-module-overrides.ts'
48
49
  import { readPeachWarmManifest } from '../../peach-engine/src/peach-warm-manifest.ts'
49
- import { resolveSootsimBridgePort } from './bridge-constants.ts'
50
+ import {
51
+ assertPeachPortEnvironment,
52
+ resolveSootsimBridgePort,
53
+ } from './bridge-constants.ts'
50
54
  import { isRecord } from './is-record.ts'
51
55
  import {
52
56
  SHELL_BRIDGE_IDENTITY_PATH,
@@ -291,9 +295,7 @@ const compatWrapperRealPackageAliases: Array<{
291
295
  find: string
292
296
  replacement: string
293
297
  }> = []
294
- for (const { specifier, packageName } of Object.values(
295
- SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES,
296
- )) {
298
+ for (const { specifier, packageName } of Object.values(PEACH_UPSTREAM_MODULES)) {
297
299
  let replacement = resolveExportsHiddenSubpath(packageName, (specifier) =>
298
300
  sootsimPluginRequire.resolve(specifier),
299
301
  )
@@ -366,7 +368,6 @@ export function sootsim(options: SootSimOptions = {}): Plugin[] {
366
368
  }
367
369
 
368
370
  return [
369
- wsBridgePlugin(),
370
371
  reactBridgePlugin(),
371
372
  {
372
373
  name: 'sootsim-published-browser-internals',
@@ -1319,10 +1320,11 @@ declare global {
1319
1320
  // across the overlap so every connected sim stays on the same websocket.
1320
1321
  const viteBridgeProcesses = (globalThis.__sootsimViteBridgeProcesses ??= new Map())
1321
1322
 
1322
- // start WS bridge server for debug CLI connectivity. exported so shell
1323
- // vite can install it standalone (engine builds via `vite build --watch`,
1324
- // which doesn't fire configureServer — the bridge has to run on shell).
1323
+ // start WS bridge server for debug CLI connectivity. the shell vite server
1324
+ // installs it explicitly and owns the one shared bridge; sootsim() never
1325
+ // does, so an isolated dev server cannot bind the shared default port.
1325
1326
  export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plugin {
1327
+ assertPeachPortEnvironment(process.env)
1326
1328
  if (
1327
1329
  options.ownedBridgePort !== undefined &&
1328
1330
  (!Number.isInteger(options.ownedBridgePort) ||
@@ -1654,6 +1656,13 @@ function sootsimConfigPlugin(
1654
1656
  return nativeLibraryStub ? { id: nativeLibraryStub } : null
1655
1657
  },
1656
1658
  },
1659
+ {
1660
+ name: 'peach-one-native-backend',
1661
+ resolveId(source: string, importer: string | undefined) {
1662
+ const backend = resolveOneNativeBackend(source, importer)
1663
+ return backend ? { id: backend } : null
1664
+ },
1665
+ },
1657
1666
  {
1658
1667
  name: 'sootsim-published-browser-internals',
1659
1668
  resolveId(source: string, importer: string | undefined) {
@@ -1726,17 +1735,6 @@ function sootsimConfigPlugin(
1726
1735
  'react-native/src/private/featureflags/ReactNativeFeatureFlags.js',
1727
1736
  ),
1728
1737
  },
1729
- ...[
1730
- 'BatchedBridge/BatchedBridge',
1731
- 'Components/View/ReactNativeStyleAttributes',
1732
- 'StyleSheet/processColor',
1733
- ].map((module) => ({
1734
- find: `@peach-internal/react-native/${module}`,
1735
- replacement: path.resolve(
1736
- workspaceNodeModules,
1737
- `react-native/Libraries/${module}.js`,
1738
- ),
1739
- })),
1740
1738
  ...Object.entries(rnLibraryStubs).map(([find, replacement]) => ({
1741
1739
  find: new RegExp(
1742
1740
  `^${find.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\.[cm]?[jt]sx?)?$`,
@@ -2227,6 +2225,8 @@ function metroNativeResolve(isAppSource: (p: string) => boolean): Plugin {
2227
2225
  filter: { id: /^\./ },
2228
2226
  handler(source, importer) {
2229
2227
  if (!importer) return null
2228
+ const oneBackend = resolveOneNativeBackend(source, importer)
2229
+ if (oneBackend) return oneBackend
2230
2230
  if (!importer.includes('node_modules') && !isAppSource(importer)) return null
2231
2231
  if (platformExts.some((ext) => source.endsWith(ext))) return null
2232
2232
 
@@ -92,7 +92,7 @@ interface Scope {
92
92
 
93
93
  type Binding =
94
94
  | { kind: 'value'; init: SyntaxNode; scope: Scope }
95
- // `key` is set when the parameter is a destructured property of that argument.
95
+ // `key` is set when the parameter is a destructured member of that argument.
96
96
  | { kind: 'param'; fn: SyntaxNode; index: number; key?: string }
97
97
  | { kind: 'opaque' }
98
98
 
@@ -147,7 +147,7 @@ function lookup(scope: Scope, name: string): Binding | undefined {
147
147
  return undefined
148
148
  }
149
149
 
150
- // a destructured parameter binds each plain property to that key of its argument.
150
+ // a destructured parameter binds each plain member to that key of its argument.
151
151
  // rest elements, defaults and nested patterns stay opaque.
152
152
  function declareParam(inner: Scope, fn: SyntaxNode, index: number, param: unknown): void {
153
153
  const name = identifierName(param)
@@ -155,6 +155,17 @@ function declareParam(inner: Scope, fn: SyntaxNode, index: number, param: unknow
155
155
  declare(inner, name, { kind: 'param', fn, index })
156
156
  return
157
157
  }
158
+ if (isNode(param) && param.type === 'ArrayPattern') {
159
+ const elements: unknown = Reflect.get(param, 'elements')
160
+ if (!Array.isArray(elements)) return
161
+ elements.forEach((element: unknown, position) => {
162
+ const name = identifierName(element)
163
+ if (name !== undefined)
164
+ declare(inner, name, { kind: 'param', fn, index, key: String(position) })
165
+ else declareOpaque(inner, patternNames(element))
166
+ })
167
+ return
168
+ }
158
169
  if (!isNode(param) || param.type !== 'ObjectPattern') {
159
170
  declareOpaque(inner, patternNames(param))
160
171
  return
@@ -334,6 +345,21 @@ function immediateArgument(
334
345
  // the value a literal holds under a static name. the last duplicate wins, as it
335
346
  // does at run time. a spread makes the literal's keys unknown.
336
347
  function propertyValue(object: SyntaxNode, name: string): SyntaxNode | undefined {
348
+ if (object.type === 'ArrayExpression') {
349
+ const index = Number(name)
350
+ const elements: unknown = Reflect.get(object, 'elements')
351
+ if (!Number.isSafeInteger(index) || index < 0 || String(index) !== name)
352
+ return undefined
353
+ if (!Array.isArray(elements)) return undefined
354
+ if (
355
+ elements
356
+ .slice(0, index + 1)
357
+ .some((element: unknown) => isNode(element) && element.type === 'SpreadElement')
358
+ )
359
+ return undefined
360
+ const value: unknown = elements[index]
361
+ return isNode(value) ? value : undefined
362
+ }
337
363
  let value: SyntaxNode | undefined
338
364
  for (const property of childNodes(Reflect.get(object, 'properties'))) {
339
365
  if (property.type === 'SpreadElement') return undefined
@@ -373,7 +399,8 @@ function resolveObject(
373
399
  depth: number,
374
400
  ): ResolvedObject | undefined {
375
401
  if (depth > MAX_RESOLUTION_DEPTH) return undefined
376
- if (expression.type === 'ObjectExpression') return { object: expression, scope }
402
+ if (expression.type === 'ObjectExpression' || expression.type === 'ArrayExpression')
403
+ return { object: expression, scope }
377
404
  if (expression.type === 'SequenceExpression') {
378
405
  const last = childNodes(Reflect.get(expression, 'expressions')).at(-1)
379
406
  return last && resolveObject(last, scope, collection, depth + 1)
@@ -54,10 +54,17 @@ const REANIMATED_IMPORT_REGEX =
54
54
  // app installed, so they compile with the engine's own plugin and carry no
55
55
  // version stamp. every other file is app code and compiles like it does on
56
56
  // device: with the plugin the app installed, stamped for the app's runtime.
57
- const ENGINE_STAND_IN_PATHS = ['/packages/peach-engine/src/', '/packages/peach-compat/src/']
57
+ const ENGINE_STAND_IN_PATHS = [
58
+ '/packages/peach-engine/src/',
59
+ '/packages/peach-compat/src/',
60
+ ]
58
61
 
59
62
  const workletsPlugins = new Map<string, { path: string; identity: string }>()
60
63
  let babelCorePromise: Promise<typeof import('@babel/core')> | null = null
64
+ const pendingWorkletTransforms = new Map<
65
+ string,
66
+ Promise<Pick<TransformResult, 'code' | 'map'> | null>
67
+ >()
61
68
 
62
69
  export function shouldApplyWorkletsPlugin(id: string, code: string): boolean {
63
70
  if (!/\.(tsx?|jsx?|mjs|cjs|mts|cts)$/.test(id)) return false
@@ -93,7 +100,10 @@ function getWorkletsPlugin(id: string): { path: string; identity: string } {
93
100
  const manifest = JSON.parse(
94
101
  fs.readFileSync(path.resolve(path.dirname(pluginPath), '..', 'package.json'), 'utf8'),
95
102
  ) as { version?: string }
96
- const plugin = { path: pluginPath, identity: `${pluginPath}@${manifest.version ?? '0'}` }
103
+ const plugin = {
104
+ path: pluginPath,
105
+ identity: `${pluginPath}@${manifest.version ?? '0'}`,
106
+ }
97
107
  workletsPlugins.set(fromDir, plugin)
98
108
  return plugin
99
109
  }
@@ -109,7 +119,7 @@ function isTypescriptFile(id: string): boolean {
109
119
  // normal dev rebuild changes a handful of files and replays the rest.
110
120
  export type WorkletBodyMode = 'executable' | 'transport'
111
121
 
112
- const CACHE_SCHEMA = 'v7'
122
+ const CACHE_SCHEMA = 'v8'
113
123
  const CACHE_ROOT = path.resolve(
114
124
  workspaceRoot,
115
125
  'node_modules',
@@ -321,23 +331,34 @@ export async function transformWorkletsCode(
321
331
  bodyMode: WorkletBodyMode = 'executable',
322
332
  ): Promise<Pick<TransformResult, 'code' | 'map'> | null> {
323
333
  const entryPath = getCacheEntryPath(code, id, sourceMaps, bodyMode)
334
+ const pending = entryPath && pendingWorkletTransforms.get(entryPath)
335
+ if (pending) return pending
324
336
  const cached = readCachedTransform(entryPath)
325
337
  if (cached) return cached
326
338
  if (!babelCorePromise) {
327
339
  babelCorePromise = import('@babel/core') as Promise<typeof import('@babel/core')>
328
340
  }
329
- const { transformAsync } = await babelCorePromise
330
- const result = await transformAsync(
331
- code,
332
- createWorkletsBabelOptions(id, sourceMaps, bodyMode),
333
- )
334
- if (!result?.code) return null
335
- const transformed = {
336
- code: result.code,
337
- map: (result.map ?? null) as TransformResult['map'],
341
+ // nested worker graphs can request the same cold transform before babel
342
+ // finishes. share only active work; watch edits must not retain old results.
343
+ const transform = babelCorePromise.then(async ({ transformAsync }) => {
344
+ const result = await transformAsync(
345
+ code,
346
+ createWorkletsBabelOptions(id, sourceMaps, bodyMode),
347
+ )
348
+ if (!result?.code) return null
349
+ const transformed = {
350
+ code: result.code,
351
+ map: (result.map ?? null) as TransformResult['map'],
352
+ }
353
+ writeCachedTransform(entryPath, transformed)
354
+ return transformed
355
+ })
356
+ if (entryPath) pendingWorkletTransforms.set(entryPath, transform)
357
+ try {
358
+ return await transform
359
+ } finally {
360
+ if (entryPath) pendingWorkletTransforms.delete(entryPath)
338
361
  }
339
- writeCachedTransform(entryPath, transformed)
340
- return transformed
341
362
  }
342
363
 
343
364
  export function transformWorkletsCodeSync(
@@ -940,6 +940,16 @@ export function readXcodeAppTarget(
940
940
  info[key.slice('INFOPLIST_KEY_'.length)] =
941
941
  value === 'YES' ? true : value === 'NO' ? false : value
942
942
  }
943
+ if (settings('GENERATE_INFOPLIST_FILE') === 'YES') {
944
+ const versions = {
945
+ CFBundleShortVersionString: 'MARKETING_VERSION',
946
+ CFBundleVersion: 'CURRENT_PROJECT_VERSION',
947
+ }
948
+ for (const [key, setting] of Object.entries(versions)) {
949
+ const value = settings(setting)
950
+ if (info[key] === undefined && value) info[key] = value
951
+ }
952
+ }
943
953
  if (
944
954
  settings('INFOPLIST_KEY_UIApplicationSceneManifest_Generation') === 'YES' &&
945
955
  info.UIApplicationSceneManifest === undefined