peachsim 0.1.854 → 0.1.871

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 (93) hide show
  1. package/cli/commands/control.ts +37 -7
  2. package/cli/commands/do-chain.ts +1 -1
  3. package/cli/commands/inspect/settling.ts +2 -0
  4. package/cli/commands/inspect.ts +2 -2
  5. package/cli/commands/preview.ts +0 -11
  6. package/cli/current-sim.ts +11 -4
  7. package/cli/drivers/playwright-sim-host.ts +21 -13
  8. package/cli/drivers/playwright.ts +2 -47
  9. package/dist-lib/agent-daemon-client.cjs +1 -1
  10. package/dist-lib/agent-events.cjs +1 -1
  11. package/dist-lib/agent-identity.cjs +1 -1
  12. package/dist-lib/agent-sessions.cjs +1 -1
  13. package/dist-lib/attached-projects.cjs +1 -1
  14. package/dist-lib/auth/shared-session.cjs +1 -1
  15. package/dist-lib/backend-origin.cjs +1 -1
  16. package/dist-lib/beta.cjs +1 -1
  17. package/dist-lib/beta.mjs +1 -1
  18. package/dist-lib/bridge-constants.cjs +1 -1
  19. package/dist-lib/bridge-contract-input.cjs +1 -1
  20. package/dist-lib/bridge-contract-input.mjs +1 -1
  21. package/dist-lib/bridge-contract.cjs +1 -1
  22. package/dist-lib/bridge-contract.mjs +1 -1
  23. package/dist-lib/bundle-channel.cjs +13 -12
  24. package/dist-lib/capture-contract.cjs +1 -1
  25. package/dist-lib/capture-contract.mjs +1 -1
  26. package/dist-lib/cli-constants.cjs +1 -1
  27. package/dist-lib/cloud-contract.cjs +1 -1
  28. package/dist-lib/cloud-contract.mjs +1 -1
  29. package/dist-lib/cloud-test-args.cjs +1 -1
  30. package/dist-lib/cloud-test-args.mjs +1 -1
  31. package/dist-lib/cloud.cjs +1 -1
  32. package/dist-lib/cloud.mjs +1 -1
  33. package/dist-lib/config.cjs +1 -1
  34. package/dist-lib/detox/index.cjs +5 -3
  35. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  36. package/dist-lib/expo-swift-bundle.cjs +13 -12
  37. package/dist-lib/expo-swift-metadata.cjs +1 -1
  38. package/dist-lib/expo-swift-metadata.mjs +1 -1
  39. package/dist-lib/home-paths.cjs +1 -1
  40. package/dist-lib/host/bridge-host.cjs +13 -12
  41. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  42. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  43. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  44. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  45. package/dist-lib/host/websocket-proxy.cjs +1 -1
  46. package/dist-lib/index.cjs +7 -3
  47. package/dist-lib/jump-to-source-babel.cjs +1 -1
  48. package/dist-lib/jump-to-source-native.cjs +1 -1
  49. package/dist-lib/kotlin-host.cjs +1 -1
  50. package/dist-lib/menu.cjs +1 -1
  51. package/dist-lib/menu.mjs +1 -1
  52. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  53. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  54. package/dist-lib/metro-production-bundle.cjs +1 -1
  55. package/dist-lib/metro-production-bundle.mjs +1 -1
  56. package/dist-lib/metro.cjs +1 -1
  57. package/dist-lib/native-app-identity.cjs +1 -1
  58. package/dist-lib/native-app-identity.mjs +1 -1
  59. package/dist-lib/native-firebase-metadata.cjs +1 -1
  60. package/dist-lib/native-firebase-metadata.mjs +1 -1
  61. package/dist-lib/plist.cjs +1 -1
  62. package/dist-lib/plist.mjs +1 -1
  63. package/dist-lib/profiles.cjs +1 -1
  64. package/dist-lib/public-brand.cjs +1 -1
  65. package/dist-lib/react-native-host-modules.cjs +1 -1
  66. package/dist-lib/react-native-host-modules.mjs +1 -1
  67. package/dist-lib/render-mode.cjs +1 -1
  68. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  69. package/dist-lib/sdk.cjs +3 -1
  70. package/dist-lib/sdk.mjs +3 -1
  71. package/dist-lib/skills.cjs +53 -48
  72. package/dist-lib/swift-compile.cjs +1 -1
  73. package/dist-lib/swift-compile.mjs +1 -1
  74. package/dist-lib/swift-package.cjs +1 -1
  75. package/dist-lib/swift-package.mjs +1 -1
  76. package/dist-lib/swift-submit.cjs +1 -1
  77. package/dist-lib/swift-submit.mjs +1 -1
  78. package/dist-lib/swift-toolchain.cjs +1 -1
  79. package/dist-lib/swift.cjs +1 -1
  80. package/dist-lib/vite-swift.cjs +14 -13
  81. package/dist-lib/vite.cjs +1 -1
  82. package/dist-lib/worklet-executable.cjs +1 -1
  83. package/dist-lib/worklet-executable.mjs +1 -1
  84. package/kotlin/fork/NOTICE +4 -2
  85. package/kotlin/fork/README.md +12 -6
  86. package/kotlin/fork/build.sh +9 -2
  87. package/kotlin/fork/fork.json +1 -1
  88. package/kotlin/fork/skia-android-shaping.patch +124 -1
  89. package/kotlin/toolchain.json +3 -3
  90. package/package.json +1 -1
  91. package/skills/contrast/SKILL.md +2 -2
  92. package/skills/peach-debug/SKILL.md +2 -2
  93. package/src/swift-host.ts +14 -15
@@ -17,5 +17,128 @@ diff --git a/modules/skshaper/src/SkShaper_harfbuzz.cpp b/modules/skshaper/src/S
17
17
  - int scale = skhb_position(font.getSize());
18
18
  + int scale = skhb_position(measurementFont->getSize());
19
19
  hb_font_set_scale(skFont.get(), scale, scale);
20
-
20
+
21
21
  return skFont;
22
+ diff --git a/modules/skparagraph/src/Run.cpp b/modules/skparagraph/src/Run.cpp
23
+ --- a/modules/skparagraph/src/Run.cpp
24
+ +++ b/modules/skparagraph/src/Run.cpp
25
+ @@ -177,9 +177,13 @@
26
+ SkScalar Run::addLetterSpacesEvenly(SkScalar space) {
27
+ SkScalar shift = 0;
28
+ for (size_t i = 0; i < this->size(); ++i) {
29
+ - fPositions[i].fX += shift;
30
+ + // modified for the Android host: boundaries bisect inter-glyph spaces.
31
+ + const auto halfSpace = i == 0 ? 0 : space / 2;
32
+ + fPositions[i].fX += shift - halfSpace;
33
+ + fOffsets[i].fX += halfSpace;
34
+ shift += space;
35
+ }
36
+ + if (this->size() > 0) shift -= space;
37
+ fPositions[this->size()].fX += shift;
38
+ fAdvance.fX += shift;
39
+ return shift;
40
+ @@ -190,8 +194,14 @@
41
+ SkScalar shift = 0;
42
+ for (size_t i = cluster->startPos(); i < cluster->endPos(); ++i) {
43
+ fPositions[i].fX += shift;
44
+ + // modified for the Android host: paint retains the inward half-space.
45
+ + const auto halfSpace = cluster->textRange().start == 0 && i == 0 ? 0 : space / 2;
46
+ + fOffsets[i].fX += halfSpace;
47
+ shift += space;
48
+ }
49
+ + // trim paragraph edges; font runs inside the paragraph keep their spacing.
50
+ + if (cluster->textRange().start == 0) shift -= space / 2;
51
+ + if (cluster->textRange().end == fOwner->text().size()) shift -= space / 2;
52
+ if (this->size() == cluster->endPos()) {
53
+ // To make calculations easier
54
+ fPositions[cluster->endPos()].fX += shift;
55
+ diff --git a/modules/skparagraph/src/TextLine.cpp b/modules/skparagraph/src/TextLine.cpp
56
+ --- a/modules/skparagraph/src/TextLine.cpp
57
+ +++ b/modules/skparagraph/src/TextLine.cpp
58
+ @@ -177,13 +177,16 @@
59
+ }
60
+ }
61
+
62
+ - // TODO: This is the fix for flutter. Must be removed...
63
+ - for (auto cluster = &start; cluster <= &end; ++cluster) {
64
+ - if (!cluster->run().isPlaceholder() && !cluster->run().isCursiveScript()) {
65
+ - fShift += cluster->getHalfLetterSpacing();
66
+ - break;
67
+ - }
68
+ - }
69
+ + // modified for the Android host: trim half-spaces at wrapped line edges.
70
+ + if (fClusterRange.start < fClusterRange.end) {
71
+ + const auto& first = fOwner->cluster(fClusterRange.start);
72
+ + const auto& last = fOwner->cluster(fClusterRange.end - 1);
73
+ + const auto leading = first.textRange().start == 0 ? 0 : first.getHalfLetterSpacing();
74
+ + const auto trailing = last.textRange().end == fOwner->text().size() ? 0 : last.getHalfLetterSpacing();
75
+ + fAdvance.fX -= leading + trailing;
76
+ + fWidthWithSpaces -= leading;
77
+ + }
78
+ +
79
+ }
80
+
81
+ void TextLine::paint(ParagraphPainter* painter, SkScalar x, SkScalar y) {
82
+ @@ -881,6 +884,10 @@
83
+ result.size = (end->isHardBreak() ? end->startPos() : end->endPos()) - start->startPos();
84
+ auto textStartInRun = run->positionX(start->startPos());
85
+ auto textStartInLine = runOffsetInLine + textOffsetInRunInLine;
86
+ + if (fClusterRange.start < fClusterRange.end) {
87
+ + const auto& first = fOwner->cluster(fClusterRange.start);
88
+ + if (first.textRange().start != 0) textStartInLine -= first.getHalfLetterSpacing();
89
+ + }
90
+ if (!run->leftToRight()) {
91
+ std::swap(start, end);
92
+ }
93
+ @@ -928,6 +935,7 @@
94
+ }
95
+
96
+ result.clip.offset(textStartInLine, 0);
97
+ + if (originalTextRange.start == fTextExcludingSpaces.start) result.clip.fLeft = std::max(result.clip.fLeft, 0.0f);
98
+ //SkDebugf("@%f[%f:%f)\n", textStartInLine, result.clip.fLeft, result.clip.fRight);
99
+
100
+ if (compareRound(result.clip.fRight, fAdvance.fX, fOwner->getApplyRoundingHack()) > 0 && !includeGhostSpaces) {
101
+ --- a/modules/skparagraph/src/TextWrapper.cpp
102
+ +++ b/modules/skparagraph/src/TextWrapper.cpp
103
+ @@ -58,12 +58,19 @@
104
+ fClip.startFrom(fEndLine.startCluster(), fEndLine.startPos());
105
+
106
+ LineBreakerWithLittleRounding breaker(maxWidth, applyRoundingHack);
107
+ + // modified for the Android host: fit the same trimmed edges as TextLine.
108
+ + const auto lineWidth = [endOfClusters](SkScalar width, const Cluster* first, const Cluster* last) {
109
+ + if (first->textRange().start != 0) width -= first->getHalfLetterSpacing();
110
+ + if (last + 1 != endOfClusters) width -= last->getHalfLetterSpacing();
111
+ + return width;
112
+ + };
113
+ Cluster* nextNonBreakingSpace = nullptr;
114
+ for (auto cluster = fEndLine.endCluster(); cluster < endOfClusters; ++cluster) {
115
+ if (cluster->isHardBreak()) {
116
+ } else if (
117
+ // TODO: Trying to deal with flutter rounding problem. Must be removed...
118
+ - SkScalar width = fWords.width() + fClusters.width() + cluster->width();
119
+ + SkScalar width = lineWidth(fWords.width() + fClusters.width() + cluster->width(),
120
+ + fEndLine.startCluster(), cluster);
121
+ breaker.breakLine(width)) {
122
+ if (cluster->isWhitespaceBreak()) {
123
+ // It's the end of the word
124
+ @@ -93,6 +100,7 @@
125
+ // Walk further to see if there is a too long word, cluster or glyph
126
+ SkScalar nextWordLength = fClusters.width();
127
+ SkScalar nextShortWordLength = nextWordLength;
128
+ + auto wordEnd = cluster;
129
+ for (auto further = cluster; further != endOfClusters; ++further) {
130
+ if (further->isSoftBreak() || further->isHardBreak() || further->isWhitespaceBreak()) {
131
+ break;
132
+ @@ -113,8 +121,10 @@
133
+ nextWordLength = std::max(nextWordLength, further->width());
134
+ } else {
135
+ nextWordLength += further->width();
136
+ - }
137
+ - }
138
+ + wordEnd = further;
139
+ + }
140
+ + }
141
+ + nextWordLength = lineWidth(nextWordLength, fClusters.startCluster(), wordEnd);
142
+ if (nextWordLength > maxWidth) {
143
+ if (nextNonBreakingSpace != nullptr) {
144
+ // We only get here if the non-breaking space improves our situation
@@ -325,9 +325,9 @@
325
325
  "skiko": "0.152.0-alpha02"
326
326
  },
327
327
  "composeRuntime": {
328
- "name": "skiko-wasm-0.152.0-alpha02-peach-637f2f8ae1fa.jar",
329
- "url": "https://r2.rnxsim.com/peach-kotlin-fork/637f2f8ae1fa804fd5ef85259d7b45877b07dd98e439eb4f3cc9560db3eba651/skiko-wasm-0.152.0-alpha02.jar",
330
- "sha256": "637f2f8ae1fa804fd5ef85259d7b45877b07dd98e439eb4f3cc9560db3eba651"
328
+ "name": "skiko-wasm-0.152.0-alpha02-peach-8b1b394f5d3b.jar",
329
+ "url": "https://r2.rnxsim.com/peach-kotlin-fork/8b1b394f5d3b3ac096c966de34855cf90625b8c0322f39d18cdfc619f21816e8/skiko-wasm-0.152.0-alpha02.jar",
330
+ "sha256": "8b1b394f5d3b3ac096c966de34855cf90625b8c0322f39d18cdfc619f21816e8"
331
331
  },
332
332
  "composeJsLibraries": [
333
333
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.854",
3
+ "version": "0.1.871",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -131,8 +131,8 @@ what this means:
131
131
  - `peach do tap login` then `peach find "Welcome"` Just Works™.
132
132
  - you only need `peach do settle <seconds>` or `peach wait idle
133
133
  --max-ms <N>` when the CLI explicitly prints
134
- `⚠ auto-wait timed out after Nms — next command may see mid-animation
135
- state`, or when the transition you care about lasts longer than ~400 ms
134
+ `⚠ auto-wait timed out after Nms (<what still moved>) — next command may
135
+ see mid-animation state`, or when the transition you care about lasts longer than ~400 ms
136
136
  (full stack navigation, crossfades, video load).
137
137
  - opt-out: `--no-wait` on a single command, `PEACH_NO_AUTO_WAIT=1`
138
138
  for a whole lane.
@@ -126,8 +126,8 @@ toast · 1 screen push`, run `peach what-happened` to see the detail.
126
126
  every CLI command already participates in a two-phase settle. you only
127
127
  need a manual wait when:
128
128
 
129
- 1. the CLI explicitly printed `⚠ auto-wait timed out after Nms — next
130
- command may see mid-animation state` *and* your next read depends on
129
+ 1. the CLI explicitly printed `⚠ auto-wait timed out after Nms (<what
130
+ still moved>) — next command may see mid-animation state` *and* your next read depends on
131
131
  the animation finishing.
132
132
  2. the transition is longer than ~400 ms (full stack navigation,
133
133
  crossfades, video first-frame, network-backed render).
package/src/swift-host.ts CHANGED
@@ -766,6 +766,7 @@ function packageSources(packagePath: string): Record<string, string> {
766
766
 
767
767
  interface SwiftPackageSnapshot {
768
768
  files: Record<string, string>
769
+ entry: string
769
770
  resourcePaths: string[]
770
771
  resources: SwiftResourceTable
771
772
  bundleFiles: SwiftBundlePack
@@ -773,11 +774,15 @@ interface SwiftPackageSnapshot {
773
774
  glue?: string
774
775
  }
775
776
 
776
- function packageSnapshot(project: SwiftProject): SwiftPackageSnapshot {
777
+ function packageSnapshot(project: SwiftProject, entry: string): SwiftPackageSnapshot {
777
778
  const files = packageSources(project.packagePath)
779
+ const layout = xcodeLayout(project.packagePath)
778
780
  const native = nativeSourceDescriptor(project.packagePath)
779
781
  return {
780
782
  files,
783
+ entry: layout
784
+ ? xcodeInputKey(layout, path.resolve(project.packagePath, entry), entry)
785
+ : entry,
781
786
  resourcePaths: swiftImplicitResourcePaths(
782
787
  resourceCandidateFiles(project.packagePath).map((file) =>
783
788
  path.relative(project.packagePath, file).split(path.sep).join(path.posix.sep),
@@ -798,28 +803,24 @@ function packageSnapshot(project: SwiftProject): SwiftPackageSnapshot {
798
803
  }
799
804
  }
800
805
 
801
- function snapshotCompileInput(
802
- snapshot: SwiftPackageSnapshot,
803
- entry: string,
804
- ): SwiftCompileInput {
806
+ function snapshotCompileInput(snapshot: SwiftPackageSnapshot): SwiftCompileInput {
805
807
  const input: SwiftCompileInput = {
806
808
  files: snapshot.files,
807
809
  resourcePaths: snapshot.resourcePaths,
808
810
  resources: snapshot.bundleFiles.files,
809
811
  images: snapshot.resources.images,
810
- entry,
812
+ entry: snapshot.entry,
811
813
  oneModule: true,
812
814
  }
813
815
  return snapshot.glue ? withNativeSourceGlue(input, snapshot.glue) : input
814
816
  }
815
817
 
816
818
  export function compileInput(packagePath: string, entry: string): SwiftCompileInput {
817
- return snapshotCompileInput(packageSnapshot(projectFor(packagePath)), entry)
819
+ return snapshotCompileInput(packageSnapshot(projectFor(packagePath), entry))
818
820
  }
819
821
 
820
822
  async function compile(
821
823
  packagePath: string,
822
- entry: string,
823
824
  stamp: string,
824
825
  moduleRootOverride: string | undefined,
825
826
  hosted: SwiftHostedCompileOptions | undefined,
@@ -838,7 +839,7 @@ async function compile(
838
839
  }
839
840
  if (hosted)
840
841
  return {
841
- ...(await compileRemote(packagePath, entry, snapshot, hosted)),
842
+ ...(await compileRemote(packagePath, snapshot, hosted)),
842
843
  stamp,
843
844
  package: content,
844
845
  }
@@ -852,12 +853,12 @@ async function compile(
852
853
  (await swiftDistributionRoot())
853
854
  if (!moduleRoot)
854
855
  return {
855
- ...(await compileRemote(packagePath, entry, snapshot)),
856
+ ...(await compileRemote(packagePath, snapshot)),
856
857
  stamp,
857
858
  package: content,
858
859
  }
859
860
  const toolchain = swiftModuleToolchain(moduleRoot)
860
- const input = snapshotCompileInput(snapshot, entry)
861
+ const input = snapshotCompileInput(snapshot)
861
862
  const targets = compileTargets(input).map((target) => target.name)
862
863
  const missing = missingSwiftModules(
863
864
  input.files,
@@ -1049,7 +1050,6 @@ async function missingModulesMessage(
1049
1050
  // immutable local asset addresses.
1050
1051
  async function compileRemote(
1051
1052
  packagePath: string,
1052
- entry: string,
1053
1053
  snapshot: SwiftPackageSnapshot,
1054
1054
  hosted?: SwiftHostedCompileOptions,
1055
1055
  ): Promise<Omit<SwiftArtifact, 'stamp' | 'package'>> {
@@ -1092,7 +1092,7 @@ async function compileRemote(
1092
1092
  resourcePaths: snapshot.resourcePaths,
1093
1093
  resources: snapshot.bundleFiles.files,
1094
1094
  images: snapshot.resources.images,
1095
- entry,
1095
+ entry: snapshot.entry,
1096
1096
  packageId: descriptor?.packageId ?? swiftPackageId(packagePath),
1097
1097
  },
1098
1098
  origin,
@@ -1154,13 +1154,12 @@ export function artifactFor(
1154
1154
  const again = () => artifactFor(project, entry, moduleRoot)
1155
1155
  return running.promise.then(again, again)
1156
1156
  }
1157
- const snapshot = packageSnapshot(project)
1157
+ const snapshot = packageSnapshot(project, entry)
1158
1158
  if (sourceStamp(project.packagePath, moduleRoot, Boolean(project.hosted)) !== stamp) {
1159
1159
  return artifactFor(project, entry, moduleRoot)
1160
1160
  }
1161
1161
  const promise = compile(
1162
1162
  project.packagePath,
1163
- entry,
1164
1163
  stamp,
1165
1164
  moduleRoot,
1166
1165
  project.hosted,