peachsim 0.1.2185 → 0.1.2187

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 (103) hide show
  1. package/cli/commands/cpu-profile.ts +6 -2
  2. package/cli/commands/shell-url.ts +3 -6
  3. package/dist-lib/agent-daemon-client.cjs +1 -1
  4. package/dist-lib/agent-events.cjs +1 -1
  5. package/dist-lib/attached-projects.cjs +1 -1
  6. package/dist-lib/auth/shared-session.cjs +1 -1
  7. package/dist-lib/backend-origin.cjs +1 -1
  8. package/dist-lib/beta.cjs +1 -1
  9. package/dist-lib/beta.mjs +1 -1
  10. package/dist-lib/bridge-constants.cjs +1 -1
  11. package/dist-lib/bridge-contract-input.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.mjs +1 -1
  13. package/dist-lib/bridge-contract.cjs +1 -1
  14. package/dist-lib/bridge-contract.mjs +1 -1
  15. package/dist-lib/bundle-channel.cjs +2755 -2385
  16. package/dist-lib/capture-contract.cjs +1 -1
  17. package/dist-lib/capture-contract.mjs +1 -1
  18. package/dist-lib/cloud-contract.cjs +1 -1
  19. package/dist-lib/cloud-contract.mjs +1 -1
  20. package/dist-lib/cloud-test-args.cjs +1 -1
  21. package/dist-lib/cloud-test-args.mjs +1 -1
  22. package/dist-lib/cloud.cjs +1 -1
  23. package/dist-lib/cloud.mjs +1 -1
  24. package/dist-lib/config.cjs +1 -1
  25. package/dist-lib/config.mjs +1 -1
  26. package/dist-lib/detox/index.cjs +2 -2
  27. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  28. package/dist-lib/expo-swift-bundle.cjs +3265 -3223
  29. package/dist-lib/expo-swift-metadata.cjs +2 -1
  30. package/dist-lib/expo-swift-metadata.mjs +2 -1
  31. package/dist-lib/home-paths.cjs +1 -1
  32. package/dist-lib/host/bridge-host.cjs +4587 -4217
  33. package/dist-lib/host/fetch-proxy-handler.cjs +8 -7
  34. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  35. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  36. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  37. package/dist-lib/host/websocket-proxy.cjs +1 -1
  38. package/dist-lib/index.cjs +474 -283
  39. package/dist-lib/jump-to-source-babel.cjs +1 -1
  40. package/dist-lib/jump-to-source-native.cjs +1 -1
  41. package/dist-lib/kotlin-host.cjs +647 -284
  42. package/dist-lib/menu.cjs +1 -1
  43. package/dist-lib/menu.mjs +1 -1
  44. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  45. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  46. package/dist-lib/metro-production-bundle.cjs +1 -1
  47. package/dist-lib/metro-production-bundle.mjs +1 -1
  48. package/dist-lib/metro.cjs +775 -584
  49. package/dist-lib/native-app-identity-project.cjs +45 -4
  50. package/dist-lib/native-app-identity-project.mjs +45 -4
  51. package/dist-lib/native-app-identity.cjs +40 -2
  52. package/dist-lib/native-app-identity.mjs +40 -2
  53. package/dist-lib/native-firebase-metadata.cjs +1 -1
  54. package/dist-lib/native-firebase-metadata.mjs +1 -1
  55. package/dist-lib/pdfium-raster.cjs +1 -1
  56. package/dist-lib/pdfium-raster.mjs +1 -1
  57. package/dist-lib/plist.cjs +1 -1
  58. package/dist-lib/plist.mjs +1 -1
  59. package/dist-lib/profiles.cjs +1 -1
  60. package/dist-lib/public-brand.cjs +1 -1
  61. package/dist-lib/public-origins-lib-esm.json +24 -24
  62. package/dist-lib/public-origins-lib.json +99 -59
  63. package/dist-lib/react-native-host-modules.cjs +1 -1
  64. package/dist-lib/react-native-host-modules.mjs +1 -1
  65. package/dist-lib/reap-browser.cjs +1 -1
  66. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  67. package/dist-lib/sdk.cjs +1 -1
  68. package/dist-lib/sdk.mjs +1 -1
  69. package/dist-lib/skills.cjs +5257 -4878
  70. package/dist-lib/swift-compile.cjs +2 -2
  71. package/dist-lib/swift-compile.mjs +2 -2
  72. package/dist-lib/swift-package.cjs +1 -1
  73. package/dist-lib/swift-package.mjs +1 -1
  74. package/dist-lib/swift-submit.cjs +1 -1
  75. package/dist-lib/swift-submit.mjs +1 -1
  76. package/dist-lib/swift-toolchain.cjs +1 -1
  77. package/dist-lib/swift.cjs +1 -1
  78. package/dist-lib/vite-swift.cjs +3 -3
  79. package/dist-lib/vite.cjs +8 -7
  80. package/dist-lib/worklet-executable.cjs +1 -1
  81. package/dist-lib/worklet-executable.mjs +1 -1
  82. package/dist-types/packages/peach-engine/src/render-worker/compositor-backend.d.ts +1 -0
  83. package/kotlin/sdk.tar.gz +0 -0
  84. package/package.json +1 -1
  85. package/runtime-companion.json +1 -1
  86. package/sdk/ios/System/Library/Frameworks/CFNetwork.framework/Headers/CFNetwork.h +10 -0
  87. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UIImageAsset.h +1 -1
  88. package/src/android-autolinking.ts +45 -4
  89. package/src/android-bridge-packages.ts +2 -2
  90. package/src/android-gradle-sources.ts +143 -0
  91. package/src/androidAutolinkingContract.ts +8 -0
  92. package/src/androidGradleContract.ts +14 -0
  93. package/src/expo-kotlin-host.ts +3 -0
  94. package/src/expo-native-workspace.ts +7 -1
  95. package/src/java-module-abi.ts +145 -0
  96. package/src/javaAbiContract.ts +14 -0
  97. package/src/kotlin-host.ts +57 -3
  98. package/src/native-app-identity-project.ts +10 -2
  99. package/src/native-app-identity.ts +15 -1
  100. package/src/nativeAppIconContract.ts +37 -0
  101. package/src/nitro-source.ts +2 -167
  102. package/src/react-native-autolinking.ts +153 -0
  103. package/src/swift-installed-targets.ts +8 -0
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2187 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -7,6 +7,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
8
  var __getProtoOf = Object.getPrototypeOf;
9
9
  var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __esm = (fn, res) => function __init() {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ };
10
13
  var __export = (target, all) => {
11
14
  for (var name in all)
12
15
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -29,6 +32,312 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
32
  ));
30
33
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
34
 
35
+ // <define:__SWIFT_COVERAGE_SOURCE_DIGESTS__>
36
+ var init_define_SWIFT_COVERAGE_SOURCE_DIGESTS = __esm({
37
+ "<define:__SWIFT_COVERAGE_SOURCE_DIGESTS__>"() {
38
+ }
39
+ });
40
+
41
+ // src/is-record.ts
42
+ function isRecord(value) {
43
+ return typeof value === "object" && value !== null && !Array.isArray(value);
44
+ }
45
+ var init_is_record = __esm({
46
+ "src/is-record.ts"() {
47
+ "use strict";
48
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
49
+ }
50
+ });
51
+
52
+ // src/home-paths.ts
53
+ function ambientHomeDir() {
54
+ return import_node_path.default.join((0, import_node_os.homedir)(), ".peach");
55
+ }
56
+ function rnxHomeDir() {
57
+ const override = process.env[PEACH_HOME_ENV];
58
+ return override && override.length > 0 ? import_node_path.default.resolve(override) : ambientHomeDir();
59
+ }
60
+ var import_node_os, import_node_path, PEACH_HOME_ENV, DAEMON_LOCKFILE_MAX_BYTES;
61
+ var init_home_paths = __esm({
62
+ "src/home-paths.ts"() {
63
+ "use strict";
64
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
65
+ import_node_os = require("node:os");
66
+ import_node_path = __toESM(require("node:path"), 1);
67
+ PEACH_HOME_ENV = "PEACH_HOME";
68
+ DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
69
+ }
70
+ });
71
+
72
+ // src/kotlin-toolchain.ts
73
+ function readToolchain(moduleRoot) {
74
+ const parsed = JSON.parse(
75
+ import_node_fs.default.readFileSync(import_node_path2.default.join(moduleRoot, "toolchain.json"), "utf8")
76
+ );
77
+ const download = (value) => {
78
+ if (!isRecord(value) || typeof value.url !== "string" || typeof value.sha256 !== "string")
79
+ throw new Error(
80
+ "peachsim kotlin/toolchain.json names a download without url and sha256"
81
+ );
82
+ return { url: value.url, sha256: value.sha256 };
83
+ };
84
+ if (!isRecord(parsed) || !isRecord(parsed.compiler) || !Array.isArray(parsed.libraries) || !Array.isArray(parsed.composeLibraries) || !Array.isArray(parsed.composeJsLibraries) || !isRecord(parsed.composeRuntime) || typeof parsed.composeRuntime.name !== "string")
85
+ throw new Error("peachsim kotlin/toolchain.json has no compiler and libraries");
86
+ const version = parsed.compiler.version;
87
+ if (typeof version !== "string")
88
+ throw new Error("peachsim kotlin/toolchain.json has no compiler version");
89
+ const libraries = (values) => values.map((library) => {
90
+ if (!isRecord(library) || typeof library.name !== "string")
91
+ throw new Error("peachsim kotlin/toolchain.json names a library without a name");
92
+ return { ...download(library), name: library.name };
93
+ });
94
+ return {
95
+ compiler: { ...download(parsed.compiler), version },
96
+ libraries: libraries(parsed.libraries),
97
+ composeLibraries: libraries(parsed.composeLibraries),
98
+ composeRuntime: {
99
+ ...download(parsed.composeRuntime),
100
+ name: parsed.composeRuntime.name
101
+ },
102
+ composeJsLibraries: parsed.composeJsLibraries.map((library) => {
103
+ if (!isRecord(library) || typeof library.name !== "string" || typeof library.module !== "string" || typeof library.file !== "string" || typeof library.archiveEntry !== "string")
104
+ throw new Error("peachsim kotlin/toolchain.json has an incomplete JS library");
105
+ return {
106
+ ...download(library),
107
+ name: library.name,
108
+ module: library.module,
109
+ file: library.file,
110
+ archiveEntry: library.archiveEntry
111
+ };
112
+ })
113
+ };
114
+ }
115
+ function kotlinHome() {
116
+ return import_node_path2.default.join(rnxHomeDir(), "kotlin");
117
+ }
118
+ async function fetchVerified(download, target) {
119
+ if (import_node_fs.default.existsSync(target)) {
120
+ if ((0, import_node_crypto.createHash)("sha256").update(import_node_fs.default.readFileSync(target)).digest("hex") !== download.sha256)
121
+ throw new Error(
122
+ `cached Kotlin download differs from its pin: ${import_node_path2.default.basename(target)}`
123
+ );
124
+ return;
125
+ }
126
+ const response = await fetch(download.url);
127
+ if (!response.ok) throw new Error(`${download.url} answered ${response.status}`);
128
+ const bytes = Buffer.from(await response.arrayBuffer());
129
+ const digest = (0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex");
130
+ if (digest !== download.sha256)
131
+ throw new Error(`${download.url} has sha256 ${digest}, expected ${download.sha256}`);
132
+ import_node_fs.default.mkdirSync(import_node_path2.default.dirname(target), { recursive: true });
133
+ const partial = `${target}.${process.pid}.partial`;
134
+ import_node_fs.default.writeFileSync(partial, bytes);
135
+ import_node_fs.default.renameSync(partial, target);
136
+ }
137
+ function ensureToolchain(toolchain) {
138
+ const key = JSON.stringify(toolchain);
139
+ const pending = toolchains.get(key);
140
+ if (pending) return pending;
141
+ const ready = (async () => {
142
+ const dir = import_node_path2.default.join(kotlinHome(), toolchain.compiler.version);
143
+ const kotlinc = import_node_path2.default.join(dir, "kotlinc", "bin", "kotlinc-wasm");
144
+ if (!import_node_fs.default.existsSync(kotlinc)) {
145
+ const zip = import_node_path2.default.join(dir, "kotlin-compiler.zip");
146
+ await fetchVerified(toolchain.compiler, zip);
147
+ await run("unzip", ["-q", "-o", zip, "-d", dir]);
148
+ import_node_fs.default.rmSync(zip);
149
+ }
150
+ const java = process.env.JAVA_HOME ? import_node_path2.default.join(process.env.JAVA_HOME, "bin", "java") : "java";
151
+ const { stderr } = await run(java, ["-XshowSettings:properties", "-version"]).catch(
152
+ () => {
153
+ throw new Error(
154
+ `Kotlin in Peach compiles with kotlinc, which needs a Java runtime (17 or newer, as android builds use); ${process.env.JAVA_HOME ? `JAVA_HOME ${process.env.JAVA_HOME} has none` : "set JAVA_HOME or put java on PATH"}`
155
+ );
156
+ }
157
+ );
158
+ const javaHome = /^\s*java\.home\s*=\s*(.+)$/m.exec(stderr)?.[1]?.trim();
159
+ if (!javaHome || !import_node_path2.default.isAbsolute(javaHome))
160
+ throw new Error("the configured Java runtime did not report an absolute java.home");
161
+ const libraries = [import_node_path2.default.join(dir, "kotlinc", "lib", "kotlin-stdlib-wasm-js.klib")];
162
+ for (const library of toolchain.libraries) {
163
+ const target = import_node_path2.default.join(dir, library.name);
164
+ await fetchVerified(library, target);
165
+ libraries.push(target);
166
+ }
167
+ return { kotlinc, libraries, javaHome };
168
+ })().catch((error) => {
169
+ toolchains.delete(key);
170
+ throw error;
171
+ });
172
+ toolchains.set(key, ready);
173
+ return ready;
174
+ }
175
+ var import_node_child_process, import_node_crypto, import_node_fs, import_node_path2, import_node_util, run, toolchains;
176
+ var init_kotlin_toolchain = __esm({
177
+ "src/kotlin-toolchain.ts"() {
178
+ "use strict";
179
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
180
+ import_node_child_process = require("node:child_process");
181
+ import_node_crypto = require("node:crypto");
182
+ import_node_fs = __toESM(require("node:fs"), 1);
183
+ import_node_path2 = __toESM(require("node:path"), 1);
184
+ import_node_util = require("node:util");
185
+ init_home_paths();
186
+ init_is_record();
187
+ run = (0, import_node_util.promisify)(import_node_child_process.execFile);
188
+ toolchains = /* @__PURE__ */ new Map();
189
+ }
190
+ });
191
+
192
+ // src/forked-script-contract.ts
193
+ var PEACH_FORKED_SCRIPT_ENV;
194
+ var init_forked_script_contract = __esm({
195
+ "src/forked-script-contract.ts"() {
196
+ "use strict";
197
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
198
+ PEACH_FORKED_SCRIPT_ENV = "PEACH_RUNS_FORKED_SCRIPTS";
199
+ }
200
+ });
201
+
202
+ // src/android-gradle-sources.ts
203
+ var android_gradle_sources_exports = {};
204
+ __export(android_gradle_sources_exports, {
205
+ resolveAndroidGradleSources: () => resolveAndroidGradleSources
206
+ });
207
+ async function resolveAndroidGradleSources(request) {
208
+ let { root } = request;
209
+ const { projects: projectDirs, variant } = request;
210
+ if (projectDirs.length === 0) return [];
211
+ if (!import_node_path6.default.isAbsolute(root) || projectDirs.some((dir) => !import_node_path6.default.isAbsolute(dir)))
212
+ throw new Error("Android Gradle source selection requires absolute project paths");
213
+ if (!variant) throw new Error("Android Gradle source selection requires a variant");
214
+ root = import_node_fs5.default.realpathSync(root);
215
+ const projects = [...new Set(projectDirs.map((dir) => import_node_fs5.default.realpathSync(dir)))];
216
+ const parent = import_node_path6.default.join(kotlinHome(), "gradle-sources");
217
+ import_node_fs5.default.mkdirSync(parent, { recursive: true });
218
+ const work = import_node_fs5.default.mkdtempSync(import_node_path6.default.join(parent, ".query-"));
219
+ const task = `peachAndroidSources${(0, import_node_crypto5.randomBytes)(8).toString("hex")}`;
220
+ const script = import_node_path6.default.join(work, "sources.gradle");
221
+ const encoded = Buffer.from(
222
+ JSON.stringify({ root, projects, variant, output: work, task })
223
+ ).toString("base64");
224
+ import_node_fs5.default.writeFileSync(script, modelQuery.replace("__PEACH_REQUEST__", encoded));
225
+ try {
226
+ await run4(
227
+ "bash",
228
+ [
229
+ import_node_path6.default.join(root, "gradlew"),
230
+ "--init-script",
231
+ script,
232
+ `${task}All`,
233
+ "--no-daemon",
234
+ "--no-configuration-cache",
235
+ "--max-workers=1",
236
+ "--console=plain"
237
+ ],
238
+ {
239
+ cwd: root,
240
+ timeout: 3e5,
241
+ maxBuffer: 8 * 1024 * 1024,
242
+ env: { ...process.env, [PEACH_FORKED_SCRIPT_ENV]: "1" }
243
+ }
244
+ );
245
+ return projects.map((projectDir, index) => {
246
+ const value = JSON.parse(
247
+ import_node_fs5.default.readFileSync(import_node_path6.default.join(work, `${index}.json`), "utf8")
248
+ );
249
+ if (!isRecord(value) || value.projectDir !== projectDir || value.variant !== variant || typeof value.projectPath !== "string" || value.applicationId !== null && typeof value.applicationId !== "string")
250
+ throw new Error("Gradle printed an invalid Android project source model");
251
+ const sources = (field) => {
252
+ const list = value[field];
253
+ if (!Array.isArray(list) || !list.every((file) => typeof file === "string" && import_node_path6.default.isAbsolute(file)))
254
+ throw new Error(`Gradle printed invalid Android ${field} source paths`);
255
+ return list.map(String);
256
+ };
257
+ return {
258
+ projectDir,
259
+ projectPath: value.projectPath,
260
+ variant,
261
+ applicationId: value.applicationId,
262
+ kotlin: sources("kotlin"),
263
+ java: sources("java")
264
+ };
265
+ });
266
+ } finally {
267
+ import_node_fs5.default.rmSync(work, { recursive: true, force: true });
268
+ }
269
+ }
270
+ var import_node_child_process4, import_node_crypto5, import_node_fs5, import_node_path6, import_node_util4, run4, modelQuery;
271
+ var init_android_gradle_sources = __esm({
272
+ "src/android-gradle-sources.ts"() {
273
+ "use strict";
274
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
275
+ import_node_child_process4 = require("node:child_process");
276
+ import_node_crypto5 = require("node:crypto");
277
+ import_node_fs5 = __toESM(require("node:fs"), 1);
278
+ import_node_path6 = __toESM(require("node:path"), 1);
279
+ import_node_util4 = require("node:util");
280
+ init_forked_script_contract();
281
+ init_is_record();
282
+ init_kotlin_toolchain();
283
+ run4 = (0, import_node_util4.promisify)(import_node_child_process4.execFile);
284
+ modelQuery = `
285
+ import groovy.json.JsonOutput
286
+ import groovy.json.JsonSlurper
287
+
288
+ def request = new JsonSlurper().parseText(new String(Base64.decoder.decode('__PEACH_REQUEST__'), 'UTF-8'))
289
+ gradle.projectsEvaluated {
290
+ if (gradle.rootProject.projectDir.canonicalPath != request.root) return
291
+ def selected = []
292
+ request.projects.eachWithIndex { directory, index ->
293
+ def matches = gradle.rootProject.allprojects.findAll { it.projectDir.canonicalPath == directory }
294
+ if (matches.size() != 1) throw new GradleException('Expected one Android project for ' + directory)
295
+ def project = matches[0]
296
+ if (project.pluginManager.hasPlugin('org.jetbrains.kotlin.multiplatform')) {
297
+ throw new GradleException('Kotlin multiplatform source selection is not supported: ' + project.path)
298
+ }
299
+ def library = project.pluginManager.hasPlugin('com.android.library')
300
+ if (!library && !project.pluginManager.hasPlugin('com.android.application')) {
301
+ throw new GradleException('Project has no Android application or library plugin: ' + project.path)
302
+ }
303
+ def android = project.extensions.getByName('android')
304
+ def variants = library ? android.libraryVariants : android.applicationVariants
305
+ def variant = variants.find { it.name == request.variant }
306
+ if (variant == null) throw new GradleException('Android variant ' + request.variant + ' is absent: ' + project.path)
307
+ def generators = []
308
+ def buildConfig = variant.generateBuildConfigProvider
309
+ if (buildConfig != null) generators.add(buildConfig)
310
+ if (project.pluginManager.hasPlugin('com.facebook.react')) {
311
+ generators.add(project.tasks.named('generateCodegenArtifactsFromSchema'))
312
+ }
313
+ def kotlin = project.tasks.findByName('compile' + variant.name.capitalize() + 'Kotlin')
314
+ def kotlinSources = kotlin == null ? project.files() : kotlin.sources
315
+ def javaSources = variant.javaCompileProvider.get().source
316
+ def query = project.tasks.register(request.task) {
317
+ dependsOn(generators)
318
+ dependsOn(kotlinSources.buildDependencies, javaSources.buildDependencies)
319
+ doLast {
320
+ def files = (kotlinSources.files + javaSources.files).unique()
321
+ def unknown = files.find { !it.name.endsWith('.kt') && !it.name.endsWith('.java') }
322
+ if (unknown != null) throw new GradleException('Unsupported Android source: ' + unknown)
323
+ new File(request.output, index.toString() + '.json').text = JsonOutput.toJson([
324
+ projectDir:project.projectDir.canonicalPath,
325
+ projectPath:project.path,
326
+ variant:variant.name,
327
+ applicationId:library ? null : variant.applicationId,
328
+ kotlin:files.findAll { it.name.endsWith('.kt') }.collect { it.absolutePath }.sort(),
329
+ java:files.findAll { it.name.endsWith('.java') }.collect { it.absolutePath }.sort()
330
+ ])
331
+ }
332
+ }
333
+ selected.add(query)
334
+ }
335
+ gradle.rootProject.tasks.register(request.task + 'All') { dependsOn(selected) }
336
+ }
337
+ `;
338
+ }
339
+ });
340
+
32
341
  // src/kotlin-host.ts
33
342
  var kotlin_host_exports = {};
34
343
  __export(kotlin_host_exports, {
@@ -44,21 +353,19 @@ __export(kotlin_host_exports, {
44
353
  serveKotlinRequest: () => serveKotlinRequest
45
354
  });
46
355
  module.exports = __toCommonJS(kotlin_host_exports);
47
- var import_node_child_process3 = require("node:child_process");
48
- var import_node_crypto4 = require("node:crypto");
49
- var import_node_fs4 = __toESM(require("node:fs"), 1);
356
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
357
+ var import_node_child_process5 = require("node:child_process");
358
+ var import_node_crypto6 = require("node:crypto");
359
+ var import_node_fs6 = __toESM(require("node:fs"), 1);
50
360
  var import_node_module = require("node:module");
51
- var import_node_path5 = __toESM(require("node:path"), 1);
52
- var import_node_util3 = require("node:util");
361
+ var import_node_path7 = __toESM(require("node:path"), 1);
362
+ var import_node_util5 = require("node:util");
53
363
  var import_acorn2 = require("acorn");
54
364
 
55
- // src/is-record.ts
56
- function isRecord(value) {
57
- return typeof value === "object" && value !== null && !Array.isArray(value);
58
- }
59
-
60
365
  // src/android-bridge-packages.ts
61
- function readMethod(value) {
366
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
367
+ init_is_record();
368
+ function readBridgeMethod(value) {
62
369
  if (!isRecord(value) || typeof value.name !== "string" || typeof value.blocking !== "boolean" || value.returns !== null && typeof value.returns !== "string" || !Array.isArray(value.params))
63
370
  throw new Error("bridge-modules printed an invalid method");
64
371
  return {
@@ -96,13 +403,136 @@ function readBridgeFiles(output) {
96
403
  modules: row.modules.map((entry) => {
97
404
  if (!isRecord(entry) || typeof entry.name !== "string" || !Array.isArray(entry.methods))
98
405
  throw new Error("bridge-modules printed an invalid module");
99
- return { name: entry.name, methods: entry.methods.map(readMethod) };
406
+ return { name: entry.name, methods: entry.methods.map(readBridgeMethod) };
100
407
  })
101
408
  };
102
409
  });
103
410
  }
104
411
 
412
+ // src/kotlin-host.ts
413
+ init_is_record();
414
+
415
+ // src/java-module-abi.ts
416
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
417
+ var import_node_child_process2 = require("node:child_process");
418
+ var import_node_crypto2 = require("node:crypto");
419
+ var import_node_fs2 = __toESM(require("node:fs"), 1);
420
+ var import_node_path3 = __toESM(require("node:path"), 1);
421
+ var import_node_util2 = require("node:util");
422
+ init_is_record();
423
+ init_kotlin_toolchain();
424
+ var run2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
425
+ var JAVA_BINDINGS_INITIALIZER = "initializeJavaBindings";
426
+ async function readJavaModuleSpecs(files, sdkRoot, toolchain) {
427
+ const digest = (0, import_node_crypto2.createHash)("sha256");
428
+ const parent = import_node_path3.default.join(kotlinHome(), "java-specs");
429
+ import_node_fs2.default.mkdirSync(parent, { recursive: true });
430
+ const work = import_node_fs2.default.mkdtempSync(import_node_path3.default.join(parent, ".read-"));
431
+ try {
432
+ const origins = /* @__PURE__ */ new Map();
433
+ for (const [index, file] of files.entries()) {
434
+ const bytes = import_node_fs2.default.readFileSync(file);
435
+ digest.update(file).update("\0").update(bytes).update("\0");
436
+ const target = import_node_path3.default.join(work, String(index), import_node_path3.default.basename(file));
437
+ import_node_fs2.default.mkdirSync(import_node_path3.default.dirname(target));
438
+ import_node_fs2.default.writeFileSync(target, bytes);
439
+ origins.set(target, file);
440
+ }
441
+ const { stdout } = await run2(
442
+ import_node_path3.default.join(toolchain.javaHome, "bin", "java"),
443
+ [
444
+ "-cp",
445
+ [
446
+ import_node_path3.default.join(sdkRoot, "tools.jar"),
447
+ import_node_path3.default.resolve(import_node_path3.default.dirname(toolchain.kotlinc), "../lib/kotlin-compiler.jar"),
448
+ import_node_path3.default.resolve(import_node_path3.default.dirname(toolchain.kotlinc), "../lib/kotlin-stdlib.jar")
449
+ ].join(import_node_path3.default.delimiter),
450
+ "dev.peach.tools.javaabi.JavaModuleSpecsKt",
451
+ ...origins.keys()
452
+ ],
453
+ { maxBuffer: 16 * 1024 * 1024 }
454
+ );
455
+ const specs = stdout.split("\n").filter(Boolean).map((line) => {
456
+ const row = JSON.parse(line);
457
+ if (!isRecord(row) || typeof row.file !== "string" || typeof row.className !== "string" || row.name !== null && typeof row.name !== "string" || typeof row.source !== "string" || !Array.isArray(row.methods))
458
+ throw new Error("Java module reader printed an invalid spec");
459
+ const file = origins.get(row.file);
460
+ if (!file) throw new Error("Java module reader named an unknown input");
461
+ return {
462
+ file,
463
+ className: row.className,
464
+ name: row.name,
465
+ source: row.source,
466
+ methods: row.methods.map(readBridgeMethod)
467
+ };
468
+ });
469
+ return { sha256: digest.digest("hex"), specs };
470
+ } finally {
471
+ import_node_fs2.default.rmSync(work, { recursive: true, force: true });
472
+ }
473
+ }
474
+ async function compileJavaModuleAbi(input) {
475
+ const { specs, work, hash, toolchain, libraries, sdkRoot, sdkLibrary, language } = input;
476
+ const directory = import_node_path3.default.join(work, "java-abi");
477
+ import_node_fs2.default.mkdirSync(directory);
478
+ const sources = specs.specs.map((spec, index) => {
479
+ const target = import_node_path3.default.join(directory, `Spec${index}.kt`);
480
+ import_node_fs2.default.writeFileSync(target, spec.source);
481
+ return target;
482
+ });
483
+ const initializer = import_node_path3.default.join(directory, "Bindings.kt");
484
+ import_node_fs2.default.writeFileSync(
485
+ initializer,
486
+ [
487
+ "package dev.peach.jni",
488
+ `internal fun ${JAVA_BINDINGS_INITIALIZER}() { error("Java bindings require the compiler plugin") }`
489
+ ].join("\n")
490
+ );
491
+ const name = `peach-java-abi-${hash}`;
492
+ await run2(
493
+ toolchain.kotlinc,
494
+ [
495
+ "-J-Xmx2g",
496
+ "-Xwasm-target=js",
497
+ "-libraries",
498
+ libraries.join(import_node_path3.default.delimiter),
499
+ `-Xplugin=${import_node_path3.default.join(sdkRoot, "plugin.jar")}`,
500
+ `-Xfriend-modules=${sdkLibrary}`,
501
+ "-language-version",
502
+ language,
503
+ "-api-version",
504
+ language,
505
+ "-nowarn",
506
+ "-ir-output-dir",
507
+ directory,
508
+ "-ir-output-name",
509
+ name,
510
+ ...sources,
511
+ initializer
512
+ ],
513
+ { maxBuffer: 16 * 1024 * 1024 }
514
+ );
515
+ const library = import_node_path3.default.join(directory, "java-abi.klib");
516
+ await run2(
517
+ import_node_path3.default.join(toolchain.javaHome, "bin", "java"),
518
+ [
519
+ "-cp",
520
+ [
521
+ import_node_path3.default.join(sdkRoot, "tools.jar"),
522
+ import_node_path3.default.resolve(import_node_path3.default.dirname(toolchain.kotlinc), "../lib/kotlin-compiler.jar"),
523
+ import_node_path3.default.resolve(import_node_path3.default.dirname(toolchain.kotlinc), "../lib/kotlin-stdlib.jar")
524
+ ].join(import_node_path3.default.delimiter),
525
+ "dev.peach.tools.platform.JavaPlatformTypesKt",
526
+ import_node_path3.default.join(directory, `${name}.klib`),
527
+ library
528
+ ],
529
+ { maxBuffer: 16 * 1024 * 1024 }
530
+ );
531
+ return library;
532
+ }
533
+
105
534
  // src/kotlin-instance-source.ts
535
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
106
536
  var import_acorn = require("acorn");
107
537
  function bindingNames(pattern) {
108
538
  if (pattern.type === "Identifier") return [pattern.name];
@@ -209,139 +639,17 @@ return { peachDisposeInstance, ${exports2.map((item) => `${JSON.stringify(item.e
209
639
  }
210
640
 
211
641
  // src/kotlin-sdk.ts
212
- var import_node_child_process2 = require("node:child_process");
213
- var import_node_crypto2 = require("node:crypto");
214
- var import_node_fs2 = __toESM(require("node:fs"), 1);
215
- var import_node_path3 = __toESM(require("node:path"), 1);
216
- var import_node_util2 = require("node:util");
217
-
218
- // src/kotlin-toolchain.ts
219
- var import_node_child_process = require("node:child_process");
220
- var import_node_crypto = require("node:crypto");
221
- var import_node_fs = __toESM(require("node:fs"), 1);
222
- var import_node_path2 = __toESM(require("node:path"), 1);
223
- var import_node_util = require("node:util");
224
-
225
- // src/home-paths.ts
226
- var import_node_os = require("node:os");
227
- var import_node_path = __toESM(require("node:path"), 1);
228
- var PEACH_HOME_ENV = "PEACH_HOME";
229
- function ambientHomeDir() {
230
- return import_node_path.default.join((0, import_node_os.homedir)(), ".peach");
231
- }
232
- function rnxHomeDir() {
233
- const override = process.env[PEACH_HOME_ENV];
234
- return override && override.length > 0 ? import_node_path.default.resolve(override) : ambientHomeDir();
235
- }
236
- var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
237
-
238
- // src/kotlin-toolchain.ts
239
- var run = (0, import_node_util.promisify)(import_node_child_process.execFile);
240
- function readToolchain(moduleRoot) {
241
- const parsed = JSON.parse(
242
- import_node_fs.default.readFileSync(import_node_path2.default.join(moduleRoot, "toolchain.json"), "utf8")
243
- );
244
- const download = (value) => {
245
- if (!isRecord(value) || typeof value.url !== "string" || typeof value.sha256 !== "string")
246
- throw new Error(
247
- "peachsim kotlin/toolchain.json names a download without url and sha256"
248
- );
249
- return { url: value.url, sha256: value.sha256 };
250
- };
251
- if (!isRecord(parsed) || !isRecord(parsed.compiler) || !Array.isArray(parsed.libraries) || !Array.isArray(parsed.composeLibraries) || !Array.isArray(parsed.composeJsLibraries) || !isRecord(parsed.composeRuntime) || typeof parsed.composeRuntime.name !== "string")
252
- throw new Error("peachsim kotlin/toolchain.json has no compiler and libraries");
253
- const version = parsed.compiler.version;
254
- if (typeof version !== "string")
255
- throw new Error("peachsim kotlin/toolchain.json has no compiler version");
256
- const libraries = (values) => values.map((library) => {
257
- if (!isRecord(library) || typeof library.name !== "string")
258
- throw new Error("peachsim kotlin/toolchain.json names a library without a name");
259
- return { ...download(library), name: library.name };
260
- });
261
- return {
262
- compiler: { ...download(parsed.compiler), version },
263
- libraries: libraries(parsed.libraries),
264
- composeLibraries: libraries(parsed.composeLibraries),
265
- composeRuntime: {
266
- ...download(parsed.composeRuntime),
267
- name: parsed.composeRuntime.name
268
- },
269
- composeJsLibraries: parsed.composeJsLibraries.map((library) => {
270
- if (!isRecord(library) || typeof library.name !== "string" || typeof library.module !== "string" || typeof library.file !== "string" || typeof library.archiveEntry !== "string")
271
- throw new Error("peachsim kotlin/toolchain.json has an incomplete JS library");
272
- return {
273
- ...download(library),
274
- name: library.name,
275
- module: library.module,
276
- file: library.file,
277
- archiveEntry: library.archiveEntry
278
- };
279
- })
280
- };
281
- }
282
- function kotlinHome() {
283
- return import_node_path2.default.join(rnxHomeDir(), "kotlin");
284
- }
285
- async function fetchVerified(download, target) {
286
- if (import_node_fs.default.existsSync(target)) {
287
- if ((0, import_node_crypto.createHash)("sha256").update(import_node_fs.default.readFileSync(target)).digest("hex") !== download.sha256)
288
- throw new Error(
289
- `cached Kotlin download differs from its pin: ${import_node_path2.default.basename(target)}`
290
- );
291
- return;
292
- }
293
- const response = await fetch(download.url);
294
- if (!response.ok) throw new Error(`${download.url} answered ${response.status}`);
295
- const bytes = Buffer.from(await response.arrayBuffer());
296
- const digest = (0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex");
297
- if (digest !== download.sha256)
298
- throw new Error(`${download.url} has sha256 ${digest}, expected ${download.sha256}`);
299
- import_node_fs.default.mkdirSync(import_node_path2.default.dirname(target), { recursive: true });
300
- const partial = `${target}.${process.pid}.partial`;
301
- import_node_fs.default.writeFileSync(partial, bytes);
302
- import_node_fs.default.renameSync(partial, target);
303
- }
304
- var toolchains = /* @__PURE__ */ new Map();
305
- function ensureToolchain(toolchain) {
306
- const key = JSON.stringify(toolchain);
307
- const pending = toolchains.get(key);
308
- if (pending) return pending;
309
- const ready = (async () => {
310
- const dir = import_node_path2.default.join(kotlinHome(), toolchain.compiler.version);
311
- const kotlinc = import_node_path2.default.join(dir, "kotlinc", "bin", "kotlinc-wasm");
312
- if (!import_node_fs.default.existsSync(kotlinc)) {
313
- const zip = import_node_path2.default.join(dir, "kotlin-compiler.zip");
314
- await fetchVerified(toolchain.compiler, zip);
315
- await run("unzip", ["-q", "-o", zip, "-d", dir]);
316
- import_node_fs.default.rmSync(zip);
317
- }
318
- const java = process.env.JAVA_HOME ? import_node_path2.default.join(process.env.JAVA_HOME, "bin", "java") : "java";
319
- const { stderr } = await run(java, ["-XshowSettings:properties", "-version"]).catch(
320
- () => {
321
- throw new Error(
322
- `Kotlin in Peach compiles with kotlinc, which needs a Java runtime (17 or newer, as android builds use); ${process.env.JAVA_HOME ? `JAVA_HOME ${process.env.JAVA_HOME} has none` : "set JAVA_HOME or put java on PATH"}`
323
- );
324
- }
325
- );
326
- const javaHome = /^\s*java\.home\s*=\s*(.+)$/m.exec(stderr)?.[1]?.trim();
327
- if (!javaHome || !import_node_path2.default.isAbsolute(javaHome))
328
- throw new Error("the configured Java runtime did not report an absolute java.home");
329
- const libraries = [import_node_path2.default.join(dir, "kotlinc", "lib", "kotlin-stdlib-wasm-js.klib")];
330
- for (const library of toolchain.libraries) {
331
- const target = import_node_path2.default.join(dir, library.name);
332
- await fetchVerified(library, target);
333
- libraries.push(target);
334
- }
335
- return { kotlinc, libraries, javaHome };
336
- })().catch((error) => {
337
- toolchains.delete(key);
338
- throw error;
339
- });
340
- toolchains.set(key, ready);
341
- return ready;
342
- }
642
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
643
+ var import_node_child_process3 = require("node:child_process");
644
+ var import_node_crypto3 = require("node:crypto");
645
+ var import_node_fs3 = __toESM(require("node:fs"), 1);
646
+ var import_node_path4 = __toESM(require("node:path"), 1);
647
+ var import_node_util3 = require("node:util");
648
+ init_kotlin_toolchain();
343
649
 
344
650
  // src/kotlinSdkContract.ts
651
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
652
+ init_is_record();
345
653
  var platform = ["Sources", "JniPlatformSources", "JniSources"];
346
654
  var KOTLIN_SDK_PROFILES = {
347
655
  core: { compose: false, directories: platform },
@@ -402,62 +710,67 @@ function readKotlinSdkManifest(source, compilerSha256) {
402
710
  }
403
711
 
404
712
  // src/kotlin-sdk.ts
405
- var run2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
713
+ var run3 = (0, import_node_util3.promisify)(import_node_child_process3.execFile);
406
714
  function verifyKotlinSdkDirectory(root, compilerSha256) {
407
715
  const expectedNames = ["manifest.json", ...KOTLIN_SDK_FILES];
408
- const names = import_node_fs2.default.readdirSync(root);
716
+ const names = import_node_fs3.default.readdirSync(root);
409
717
  if (names.length !== expectedNames.length || names.some((name) => !expectedNames.includes(name)))
410
718
  throw new Error("Kotlin SDK directory contains unexpected inputs");
411
- const manifestStat = import_node_fs2.default.lstatSync(import_node_path3.default.join(root, "manifest.json"));
719
+ const manifestStat = import_node_fs3.default.lstatSync(import_node_path4.default.join(root, "manifest.json"));
412
720
  if (!manifestStat.isFile() || manifestStat.nlink !== 1)
413
721
  throw new Error("Kotlin SDK manifest is not a regular file");
414
722
  const manifest = readKotlinSdkManifest(
415
- import_node_fs2.default.readFileSync(import_node_path3.default.join(root, "manifest.json"), "utf8"),
723
+ import_node_fs3.default.readFileSync(import_node_path4.default.join(root, "manifest.json"), "utf8"),
416
724
  compilerSha256
417
725
  );
418
726
  for (const [name, expected] of Object.entries(manifest.files)) {
419
- const target = import_node_path3.default.join(root, name);
420
- const stat = import_node_fs2.default.lstatSync(target);
727
+ const target = import_node_path4.default.join(root, name);
728
+ const stat = import_node_fs3.default.lstatSync(target);
421
729
  if (!stat.isFile() || stat.nlink !== 1)
422
730
  throw new Error(`Kotlin SDK binary is not a regular file: ${name}`);
423
- const bytes = import_node_fs2.default.readFileSync(target);
424
- if (bytes.length !== expected.bytes || (0, import_node_crypto2.createHash)("sha256").update(bytes).digest("hex") !== expected.sha256)
731
+ const bytes = import_node_fs3.default.readFileSync(target);
732
+ if (bytes.length !== expected.bytes || (0, import_node_crypto3.createHash)("sha256").update(bytes).digest("hex") !== expected.sha256)
425
733
  throw new Error(`Kotlin SDK binary differs from its manifest: ${name}`);
426
734
  }
427
735
  return manifest;
428
736
  }
429
737
  async function installKotlinSdkArchive(archive, compilerSha256) {
430
- const sha256 = (0, import_node_crypto2.createHash)("sha256").update(archive).digest("hex");
431
- const parent = import_node_path3.default.join(kotlinHome(), "sdk");
432
- const root = import_node_path3.default.join(parent, sha256);
433
- if (import_node_fs2.default.existsSync(root))
738
+ const sha256 = (0, import_node_crypto3.createHash)("sha256").update(archive).digest("hex");
739
+ const parent = import_node_path4.default.join(kotlinHome(), "sdk");
740
+ const root = import_node_path4.default.join(parent, sha256);
741
+ if (import_node_fs3.default.existsSync(root))
434
742
  return { root, sha256, manifest: verifyKotlinSdkDirectory(root, compilerSha256) };
435
- import_node_fs2.default.mkdirSync(parent, { recursive: true });
436
- const work = import_node_fs2.default.mkdtempSync(import_node_path3.default.join(parent, ".install-"));
743
+ import_node_fs3.default.mkdirSync(parent, { recursive: true });
744
+ const work = import_node_fs3.default.mkdtempSync(import_node_path4.default.join(parent, ".install-"));
437
745
  try {
438
- const packed = import_node_path3.default.join(work, "sdk.tar.gz");
439
- import_node_fs2.default.writeFileSync(packed, archive);
440
- const { stdout } = await run2("tar", ["-tzf", packed]);
746
+ const packed = import_node_path4.default.join(work, "sdk.tar.gz");
747
+ import_node_fs3.default.writeFileSync(packed, archive);
748
+ const { stdout } = await run3("tar", ["-tzf", packed]);
441
749
  const names = stdout.trim().split("\n");
442
750
  const expected = ["manifest.json", ...KOTLIN_SDK_FILES];
443
751
  if (names.length !== expected.length || new Set(names).size !== names.length || names.some((name) => !expected.includes(name)))
444
752
  throw new Error("Kotlin SDK archive contains unexpected inputs");
445
- await run2("tar", ["-xzf", packed, "-C", work, "--", ...expected]);
446
- import_node_fs2.default.rmSync(packed);
753
+ await run3("tar", ["-xzf", packed, "-C", work, "--", ...expected]);
754
+ import_node_fs3.default.rmSync(packed);
447
755
  const manifest = verifyKotlinSdkDirectory(work, compilerSha256);
448
756
  try {
449
- import_node_fs2.default.renameSync(work, root);
757
+ import_node_fs3.default.renameSync(work, root);
450
758
  } catch (error) {
451
- if (!import_node_fs2.default.existsSync(root)) throw error;
759
+ if (!import_node_fs3.default.existsSync(root)) throw error;
452
760
  verifyKotlinSdkDirectory(root, compilerSha256);
453
761
  }
454
762
  return { root, sha256, manifest };
455
763
  } finally {
456
- import_node_fs2.default.rmSync(work, { recursive: true, force: true });
764
+ import_node_fs3.default.rmSync(work, { recursive: true, force: true });
457
765
  }
458
766
  }
459
767
 
768
+ // src/kotlin-host.ts
769
+ init_kotlin_toolchain();
770
+
460
771
  // src/kotlin-view-models.ts
772
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
773
+ init_is_record();
461
774
  var VIEW_MODEL = "androidx.lifecycle.ViewModel";
462
775
  var ANDROID_VIEW_MODEL = "androidx.lifecycle.AndroidViewModel";
463
776
  var APPLICATION = "android.app.Application";
@@ -533,45 +846,49 @@ function viewModelClasses(rows) {
533
846
  }
534
847
 
535
848
  // src/kotlin-module.ts
536
- var import_node_crypto3 = require("node:crypto");
537
- var import_node_fs3 = __toESM(require("node:fs"), 1);
538
- var import_node_path4 = __toESM(require("node:path"), 1);
849
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
850
+ var import_node_crypto4 = require("node:crypto");
851
+ var import_node_fs4 = __toESM(require("node:fs"), 1);
852
+ var import_node_path5 = __toESM(require("node:path"), 1);
539
853
  var import_node_url = require("node:url");
540
854
 
541
855
  // cli/standalone.ts
856
+ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
542
857
  var IS_STANDALONE = typeof __SOOTSIM_STANDALONE__ !== "undefined" && __SOOTSIM_STANDALONE__;
543
858
 
544
859
  // src/kotlin-module.ts
860
+ init_home_paths();
861
+ init_is_record();
545
862
  var installedRoot;
546
863
  function peachKotlinModuleRoot() {
547
864
  if (!IS_STANDALONE)
548
- return import_node_path4.default.resolve(import_node_path4.default.dirname((0, import_node_url.fileURLToPath)(__sootsim_import_meta_url)), "..", "kotlin");
865
+ return import_node_path5.default.resolve(import_node_path5.default.dirname((0, import_node_url.fileURLToPath)(__sootsim_import_meta_url)), "..", "kotlin");
549
866
  if (installedRoot) return installedRoot;
550
867
  const files = __PEACH_BUNDLED_KOTLIN__;
551
- const digest = (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(files)).digest("hex");
552
- const parent = import_node_path4.default.join(rnxHomeDir(), "kotlin", "modules");
553
- const root = import_node_path4.default.join(parent, digest);
554
- import_node_fs3.default.mkdirSync(parent, { recursive: true });
555
- if (!import_node_fs3.default.existsSync(root)) {
556
- const pending = import_node_fs3.default.mkdtempSync(import_node_path4.default.join(parent, ".install-"));
868
+ const digest = (0, import_node_crypto4.createHash)("sha256").update(JSON.stringify(files)).digest("hex");
869
+ const parent = import_node_path5.default.join(rnxHomeDir(), "kotlin", "modules");
870
+ const root = import_node_path5.default.join(parent, digest);
871
+ import_node_fs4.default.mkdirSync(parent, { recursive: true });
872
+ if (!import_node_fs4.default.existsSync(root)) {
873
+ const pending = import_node_fs4.default.mkdtempSync(import_node_path5.default.join(parent, ".install-"));
557
874
  try {
558
875
  for (const [name, contents] of Object.entries(files)) {
559
- const file = import_node_path4.default.join(pending, name);
560
- import_node_fs3.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
561
- import_node_fs3.default.writeFileSync(file, Buffer.from(contents, "base64"));
876
+ const file = import_node_path5.default.join(pending, name);
877
+ import_node_fs4.default.mkdirSync(import_node_path5.default.dirname(file), { recursive: true });
878
+ import_node_fs4.default.writeFileSync(file, Buffer.from(contents, "base64"));
562
879
  }
563
880
  try {
564
- import_node_fs3.default.renameSync(pending, root);
881
+ import_node_fs4.default.renameSync(pending, root);
565
882
  } catch (error) {
566
883
  if (!isRecord(error) || error.code !== "EEXIST" && error.code !== "ENOTEMPTY")
567
884
  throw error;
568
885
  }
569
886
  } finally {
570
- import_node_fs3.default.rmSync(pending, { recursive: true, force: true });
887
+ import_node_fs4.default.rmSync(pending, { recursive: true, force: true });
571
888
  }
572
889
  }
573
890
  for (const [name, contents] of Object.entries(files)) {
574
- if (!import_node_fs3.default.readFileSync(import_node_path4.default.join(root, name)).equals(Buffer.from(contents, "base64")))
891
+ if (!import_node_fs4.default.readFileSync(import_node_path5.default.join(root, name)).equals(Buffer.from(contents, "base64")))
575
892
  throw new Error(`packaged Kotlin module differs from this CLI: ${name}`);
576
893
  }
577
894
  installedRoot = root;
@@ -579,20 +896,20 @@ function peachKotlinModuleRoot() {
579
896
  }
580
897
 
581
898
  // src/kotlin-host.ts
582
- var run3 = (0, import_node_util3.promisify)(import_node_child_process3.execFile);
899
+ var run5 = (0, import_node_util5.promisify)(import_node_child_process5.execFile);
583
900
  function loadKotlinSdk(moduleRoot, toolchain) {
584
901
  return installKotlinSdkArchive(
585
- import_node_fs4.default.readFileSync(import_node_path5.default.join(moduleRoot, "sdk.tar.gz")),
902
+ import_node_fs6.default.readFileSync(import_node_path7.default.join(moduleRoot, "sdk.tar.gz")),
586
903
  toolchain.compiler.sha256
587
904
  );
588
905
  }
589
906
  var KOTLIN_ARTIFACT_PREFIX = "/__peach/kotlin-artifact/";
590
907
  function appKotlinLanguage(root) {
591
- const reactNative = import_node_path5.default.dirname(
592
- (0, import_node_module.createRequire)(import_node_path5.default.join(root, "package.json")).resolve("react-native/package.json")
908
+ const reactNative = import_node_path7.default.dirname(
909
+ (0, import_node_module.createRequire)(import_node_path7.default.join(root, "package.json")).resolve("react-native/package.json")
593
910
  );
594
- const versions = import_node_fs4.default.readFileSync(
595
- import_node_path5.default.join(reactNative, "gradle", "libs.versions.toml"),
911
+ const versions = import_node_fs6.default.readFileSync(
912
+ import_node_path7.default.join(reactNative, "gradle", "libs.versions.toml"),
596
913
  "utf8"
597
914
  );
598
915
  const match = /^kotlin\s*=\s*"(\d+)\.(\d+)/m.exec(versions);
@@ -614,9 +931,9 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([
614
931
  function kotlinSources(root, skip = SKIP_DIRS) {
615
932
  const sources = [];
616
933
  const walk = (dir) => {
617
- for (const entry of import_node_fs4.default.readdirSync(dir, { withFileTypes: true })) {
934
+ for (const entry of import_node_fs6.default.readdirSync(dir, { withFileTypes: true })) {
618
935
  if (entry.name.startsWith(".") || skip.has(entry.name)) continue;
619
- const full = import_node_path5.default.join(dir, entry.name);
936
+ const full = import_node_path7.default.join(dir, entry.name);
620
937
  if (entry.isDirectory()) walk(full);
621
938
  else if (entry.isFile() && entry.name.endsWith(".kt")) sources.push(full);
622
939
  }
@@ -644,10 +961,12 @@ function entrySource(ids) {
644
961
  "",
645
962
  "@OptIn(kotlin.js.ExperimentalJsExport::class)",
646
963
  "@JsExport",
647
- "fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {",
964
+ "fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String, properties: String) {",
648
965
  " Build.setDevice(model, release, apiLevel)",
649
966
  " java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))",
650
967
  " java.util.TimeZone.setDevice(timeZone)",
968
+ " dev.peach.android.ProcessSettings.configure(settings)",
969
+ " android.os.SystemProperties.configure(properties)",
651
970
  "}",
652
971
  "",
653
972
  "@OptIn(kotlin.js.ExperimentalJsExport::class, kotlinx.coroutines.DelicateCoroutinesApi::class)",
@@ -678,7 +997,7 @@ function entrySource(ids) {
678
997
  var BUILD_FORMAT = 19;
679
998
  var builds = /* @__PURE__ */ new Map();
680
999
  function buildsDir() {
681
- return import_node_path5.default.join(kotlinHome(), "builds");
1000
+ return import_node_path7.default.join(kotlinHome(), "builds");
682
1001
  }
683
1002
  async function kotlinArtifact(root, moduleRoot, origin, target = "app") {
684
1003
  const { kotlinSourceId, nativeSourceContract, renderKotlinSourceGlue } = await import("vxrn/native-source-contract");
@@ -691,7 +1010,7 @@ async function kotlinArtifact(root, moduleRoot, origin, target = "app") {
691
1010
  const viewIds = [];
692
1011
  let usesCompose = false;
693
1012
  for (const file of sources) {
694
- const source = import_node_fs4.default.readFileSync(file, "utf8");
1013
+ const source = import_node_fs6.default.readFileSync(file, "utf8");
695
1014
  if (/\bandroidx\.compose\./.test(source)) usesCompose = true;
696
1015
  const contract = nativeSourceContract(file, source);
697
1016
  if (contract.modules.length === 0 && contract.views.length === 0) continue;
@@ -781,24 +1100,24 @@ function readExpoTypes(output) {
781
1100
  }
782
1101
  var toolScans = /* @__PURE__ */ new Map();
783
1102
  async function scanSources(tool, parse3, toolchain, moduleRoot, files) {
784
- const digest = (0, import_node_crypto4.createHash)("sha256").update(JSON.stringify(toolchain.compiler));
1103
+ const digest = (0, import_node_crypto6.createHash)("sha256").update(JSON.stringify(toolchain.compiler));
785
1104
  const sdk = await loadKotlinSdk(moduleRoot, toolchain);
786
- digest.update(import_node_fs4.default.readFileSync(import_node_path5.default.join(moduleRoot, "sdk.tar.gz")));
1105
+ digest.update(import_node_fs6.default.readFileSync(import_node_path7.default.join(moduleRoot, "sdk.tar.gz")));
787
1106
  digest.update(tool);
788
- for (const file of files) digest.update(`${file}\0${import_node_fs4.default.readFileSync(file, "utf8")}\0`);
1107
+ for (const file of files) digest.update(`${file}\0${import_node_fs6.default.readFileSync(file, "utf8")}\0`);
789
1108
  const key = digest.digest("hex");
790
1109
  let scan = toolScans.get(key);
791
1110
  if (!scan) {
792
1111
  scan = (async () => {
793
1112
  const { kotlinc } = await ensureToolchain(toolchain);
794
- const { stdout } = await run3(
795
- import_node_path5.default.join(import_node_path5.default.dirname(kotlinc), "kotlin"),
1113
+ const { stdout } = await run5(
1114
+ import_node_path7.default.join(import_node_path7.default.dirname(kotlinc), "kotlin"),
796
1115
  [
797
1116
  "-cp",
798
1117
  [
799
- import_node_path5.default.resolve(import_node_path5.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
800
- import_node_path5.default.join(sdk.root, "tools.jar")
801
- ].join(import_node_path5.default.delimiter),
1118
+ import_node_path7.default.resolve(import_node_path7.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
1119
+ import_node_path7.default.join(sdk.root, "tools.jar")
1120
+ ].join(import_node_path7.default.delimiter),
802
1121
  tool,
803
1122
  ...files
804
1123
  ],
@@ -816,7 +1135,7 @@ async function scanSources(tool, parse3, toolchain, moduleRoot, files) {
816
1135
  async function scanExpoTypes(toolchain, moduleRoot, sources) {
817
1136
  const candidates = sources.filter(
818
1137
  (file) => /\bRecord\b|\benum\s+class\b|\bExpoComposeView\b|\bExpoView\b|\bComposeProps\b|:\s*(?:[A-Za-z0-9_.]+\.)?(?:View|FrameLayout|LinearLayout|ViewGroup)\b/.test(
819
- import_node_fs4.default.readFileSync(file, "utf8")
1138
+ import_node_fs6.default.readFileSync(file, "utf8")
820
1139
  )
821
1140
  );
822
1141
  if (candidates.length === 0) return [];
@@ -1005,7 +1324,7 @@ function expoTypeSources(files) {
1005
1324
  )
1006
1325
  ];
1007
1326
  if (edits.length > 0 || views.length > 0) {
1008
- let text = import_node_fs4.default.readFileSync(file.file, "utf8").replaceAll("\r\n", "\n");
1327
+ let text = import_node_fs6.default.readFileSync(file.file, "utf8").replaceAll("\r\n", "\n");
1009
1328
  for (const { range, owner, field } of edits.sort((a, b) => b.range[0] - a.range[0]))
1010
1329
  text = `${text.slice(0, range[0])}dev.peach.expo.PeachExpoTypes.initial(${owner}::class, ${literal(field.key)}, ${field.required}) { ${text.slice(range[0], range[1])} }${text.slice(range[1])}`;
1011
1330
  if (views.length > 0) {
@@ -1021,7 +1340,7 @@ function expoTypeSources(files) {
1021
1340
  `${file.package ? `${file.package}.` : ""}peachExpoViews${index}()`
1022
1341
  );
1023
1342
  }
1024
- const name = `PeachExpoSource_${index}_${import_node_path5.default.basename(file.file)}`;
1343
+ const name = `PeachExpoSource_${index}_${import_node_path7.default.basename(file.file)}`;
1025
1344
  generated[name] = text;
1026
1345
  origins[name] = file.file;
1027
1346
  }
@@ -1040,11 +1359,30 @@ function expoTypeSources(files) {
1040
1359
  return { generated, origins, registrations };
1041
1360
  }
1042
1361
  async function expoKotlinArtifact(root, moduleRoot, origin, modules) {
1362
+ if (modules.gradleSources) {
1363
+ const { resolveAndroidGradleSources: resolveAndroidGradleSources2 } = await Promise.resolve().then(() => (init_android_gradle_sources(), android_gradle_sources_exports));
1364
+ const projects = await resolveAndroidGradleSources2(modules.gradleSources);
1365
+ modules = {
1366
+ ...modules,
1367
+ sources: [
1368
+ .../* @__PURE__ */ new Set([
1369
+ ...modules.sources,
1370
+ ...projects.flatMap((project) => project.kotlin)
1371
+ ])
1372
+ ],
1373
+ javaSpecs: [
1374
+ .../* @__PURE__ */ new Set([
1375
+ ...modules.javaSpecs ?? [],
1376
+ ...projects.flatMap((project) => project.java)
1377
+ ])
1378
+ ]
1379
+ };
1380
+ }
1043
1381
  const toolchain = readToolchain(moduleRoot);
1044
1382
  const language = appKotlinLanguage(root);
1045
1383
  const scanned = await scanExpoTypes(toolchain, moduleRoot, modules.sources);
1046
1384
  const usesCompose = scanned.some((file) => file.views.length > 0) || modules.sources.some(
1047
- (file) => /\bandroidx\.compose\./.test(import_node_fs4.default.readFileSync(file, "utf8"))
1385
+ (file) => /\bandroidx\.compose\./.test(import_node_fs6.default.readFileSync(file, "utf8"))
1048
1386
  );
1049
1387
  const types = expoTypeSources(scanned);
1050
1388
  const rewritten = new Set(Object.values(types.origins));
@@ -1063,10 +1401,12 @@ async function expoKotlinArtifact(root, moduleRoot, origin, modules) {
1063
1401
  " ))",
1064
1402
  "}",
1065
1403
  "",
1066
- "@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {",
1404
+ "@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String, properties: String) {",
1067
1405
  " android.os.Build.setDevice(model, release, apiLevel)",
1068
1406
  " java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))",
1069
1407
  " java.util.TimeZone.setDevice(timeZone)",
1408
+ " dev.peach.android.ProcessSettings.configure(settings)",
1409
+ " android.os.SystemProperties.configure(properties)",
1070
1410
  " PeachExpoRuntime.configureProcessLocale(locale)",
1071
1411
  "}",
1072
1412
  "",
@@ -1088,6 +1428,7 @@ async function expoKotlinArtifact(root, moduleRoot, origin, modules) {
1088
1428
  toolchain,
1089
1429
  language,
1090
1430
  sources: modules.sources.filter((file) => !rewritten.has(file)),
1431
+ javaSpecs: modules.javaSpecs,
1091
1432
  generated: {
1092
1433
  ...types.generated,
1093
1434
  "PeachExpoEntry.kt": entry,
@@ -1268,7 +1609,7 @@ function appResourceSources(app) {
1268
1609
  entries: app.drawables.map((drawable) => ({
1269
1610
  name: drawable.name,
1270
1611
  init: `listOf(
1271
- ${drawable.files.map((file) => drawableInit(file, import_node_path5.default.relative(app.moduleDir, file.file))).join(",\n")}
1612
+ ${drawable.files.map((file) => drawableInit(file, import_node_path7.default.relative(app.moduleDir, file.file))).join(",\n")}
1272
1613
  )`
1273
1614
  }))
1274
1615
  },
@@ -1337,7 +1678,7 @@ function drawableInit(drawable, file) {
1337
1678
  if (drawable.kind === "xml") return `PeachDrawable.Xml(${where})`;
1338
1679
  if (drawable.kind === "bitmap")
1339
1680
  return `PeachDrawable.Bitmap(${where}, ${drawable.ninePatch}, ${literal(
1340
- import_node_fs4.default.readFileSync(drawable.file).toString("base64")
1681
+ import_node_fs6.default.readFileSync(drawable.file).toString("base64")
1341
1682
  )})`;
1342
1683
  const vector = drawable.vector;
1343
1684
  const float = (value) => `${value}f`;
@@ -1397,11 +1738,13 @@ async function compileKotlin(input, origin) {
1397
1738
  sdkProfile,
1398
1739
  usesCompose,
1399
1740
  usesSerialization = false,
1400
- viewModels
1741
+ viewModels,
1742
+ javaSpecs = []
1401
1743
  } = input;
1402
1744
  const sdk = await loadKotlinSdk(moduleRoot, toolchain);
1403
- const plugin = import_node_path5.default.join(sdk.root, "plugin.jar");
1404
- const sdkLibrary = import_node_path5.default.join(sdk.root, `${sdkProfile}.klib`);
1745
+ const plugin = import_node_path7.default.join(sdk.root, "plugin.jar");
1746
+ const sdkLibrary = import_node_path7.default.join(sdk.root, `${sdkProfile}.klib`);
1747
+ const java = javaSpecs.length ? await readJavaModuleSpecs(javaSpecs, sdk.root, await ensureToolchain(toolchain)) : null;
1405
1748
  const generated = {
1406
1749
  ...sourceGenerated,
1407
1750
  "PeachBindingsInitialization.kt": [
@@ -1413,6 +1756,7 @@ async function compileKotlin(input, origin) {
1413
1756
  "@JsExport fun peachInitializeModuleBindings() {",
1414
1757
  " if (!initialized) {",
1415
1758
  " requireIncomingBindings()",
1759
+ ...java ? [` ${JAVA_BINDINGS_INITIALIZER}()`] : [],
1416
1760
  " initializeApplicationIncomingBindings()",
1417
1761
  ...sourceGenerated["PeachViews.kt"] ? [" initializeApplicationViews()"] : [],
1418
1762
  " initialized = true",
@@ -1422,9 +1766,9 @@ async function compileKotlin(input, origin) {
1422
1766
  };
1423
1767
  const inputs = sources.map((file) => ({
1424
1768
  file,
1425
- bytes: import_node_fs4.default.readFileSync(file)
1769
+ bytes: import_node_fs6.default.readFileSync(file)
1426
1770
  }));
1427
- const digest = (0, import_node_crypto4.createHash)("sha256");
1771
+ const digest = (0, import_node_crypto6.createHash)("sha256");
1428
1772
  digest.update(
1429
1773
  JSON.stringify({
1430
1774
  format: BUILD_FORMAT,
@@ -1432,11 +1776,12 @@ async function compileKotlin(input, origin) {
1432
1776
  language,
1433
1777
  sdk: sdk.sha256,
1434
1778
  sdkProfile,
1435
- usesSerialization
1779
+ usesSerialization,
1780
+ java: java?.sha256
1436
1781
  })
1437
1782
  );
1438
1783
  for (const { file, bytes } of inputs)
1439
- digest.update(import_node_path5.default.relative(root, file)).update("\0").update(bytes).update("\0");
1784
+ digest.update(import_node_path7.default.relative(root, file)).update("\0").update(bytes).update("\0");
1440
1785
  if (viewModels) digest.update(viewModels.toolClass);
1441
1786
  for (const [name, text] of Object.entries(generated))
1442
1787
  digest.update(`${name}\0${text}\0`);
@@ -1445,37 +1790,39 @@ async function compileKotlin(input, origin) {
1445
1790
  url: `${origin}${KOTLIN_ARTIFACT_PREFIX}${hash}/app.mjs`,
1446
1791
  hash
1447
1792
  };
1448
- const out = import_node_path5.default.join(buildsDir(), hash);
1449
- if (import_node_fs4.default.existsSync(import_node_path5.default.join(out, "js", "app.wasm"))) return artifact;
1793
+ const out = import_node_path7.default.join(buildsDir(), hash);
1794
+ if (import_node_fs6.default.existsSync(import_node_path7.default.join(out, "js", "app.wasm"))) return artifact;
1450
1795
  const pending = builds.get(hash);
1451
1796
  if (pending) return pending;
1452
1797
  const build = (async () => {
1453
1798
  const ready = await ensureToolchain(toolchain);
1454
1799
  const { kotlinc } = ready;
1455
1800
  const libraries = [...ready.libraries, sdkLibrary];
1456
- const composeRuntime = import_node_path5.default.join(
1801
+ const composeRuntime = import_node_path7.default.join(
1457
1802
  kotlinHome(),
1458
1803
  toolchain.compiler.version,
1459
1804
  toolchain.composeRuntime.name
1460
1805
  );
1461
1806
  if (usesCompose) {
1462
1807
  for (const library of toolchain.composeLibraries) {
1463
- const target = import_node_path5.default.join(kotlinHome(), toolchain.compiler.version, library.name);
1808
+ const target = import_node_path7.default.join(kotlinHome(), toolchain.compiler.version, library.name);
1464
1809
  await fetchVerified(library, target);
1465
1810
  libraries.push(target);
1466
1811
  }
1467
1812
  await fetchVerified(toolchain.composeRuntime, composeRuntime);
1468
1813
  }
1469
- import_node_fs4.default.mkdirSync(buildsDir(), { recursive: true });
1470
- const work = import_node_fs4.default.mkdtempSync(import_node_path5.default.join(buildsDir(), `${hash}-`));
1471
- const generatedDir = import_node_path5.default.join(work, "generated");
1472
- import_node_fs4.default.mkdirSync(generatedDir);
1814
+ import_node_fs6.default.mkdirSync(buildsDir(), { recursive: true });
1815
+ const work = import_node_fs6.default.mkdtempSync(import_node_path7.default.join(buildsDir(), `${hash}-`));
1816
+ const javaLibrary = java ? import_node_path7.default.join(work, "java-abi", "java-abi.klib") : null;
1817
+ if (javaLibrary) libraries.push(javaLibrary);
1818
+ const generatedDir = import_node_path7.default.join(work, "generated");
1819
+ import_node_fs6.default.mkdirSync(generatedDir);
1473
1820
  for (const [name, text] of Object.entries(generated))
1474
- import_node_fs4.default.writeFileSync(import_node_path5.default.join(generatedDir, name), text);
1821
+ import_node_fs6.default.writeFileSync(import_node_path7.default.join(generatedDir, name), text);
1475
1822
  const compiledSources = inputs.map(({ file, bytes }, index) => {
1476
- const target = import_node_path5.default.join(work, "sources", String(index), import_node_path5.default.basename(file));
1477
- import_node_fs4.default.mkdirSync(import_node_path5.default.dirname(target), { recursive: true });
1478
- import_node_fs4.default.writeFileSync(target, bytes);
1823
+ const target = import_node_path7.default.join(work, "sources", String(index), import_node_path7.default.basename(file));
1824
+ import_node_fs6.default.mkdirSync(import_node_path7.default.dirname(target), { recursive: true });
1825
+ import_node_fs6.default.writeFileSync(target, bytes);
1479
1826
  return { file, target };
1480
1827
  });
1481
1828
  const common = [
@@ -1484,19 +1831,19 @@ async function compileKotlin(input, origin) {
1484
1831
  "-Xallow-kotlin-package",
1485
1832
  "-Xwasm-target=js",
1486
1833
  "-libraries",
1487
- libraries.join(import_node_path5.default.delimiter)
1834
+ libraries.join(import_node_path7.default.delimiter)
1488
1835
  ];
1489
- const compileKlib = (outputDir) => run3(
1836
+ const compileKlib = (outputDir) => run5(
1490
1837
  kotlinc,
1491
1838
  [
1492
1839
  ...common,
1493
1840
  `-Xplugin=${plugin}`,
1494
- `-Xfriend-modules=${sdkLibrary}`,
1841
+ `-Xfriend-modules=${[sdkLibrary, ...javaLibrary ? [javaLibrary] : []].join(import_node_path7.default.delimiter)}`,
1495
1842
  ...usesCompose ? [
1496
- `-Xplugin=${import_node_path5.default.resolve(import_node_path5.default.dirname(kotlinc), "../lib/compose-compiler-plugin.jar")}`
1843
+ `-Xplugin=${import_node_path7.default.resolve(import_node_path7.default.dirname(kotlinc), "../lib/compose-compiler-plugin.jar")}`
1497
1844
  ] : [],
1498
1845
  ...usesSerialization ? [
1499
- `-Xplugin=${import_node_path5.default.resolve(import_node_path5.default.dirname(kotlinc), "../lib/kotlinx-serialization-compiler-plugin.jar")}`
1846
+ `-Xplugin=${import_node_path7.default.resolve(import_node_path7.default.dirname(kotlinc), "../lib/kotlinx-serialization-compiler-plugin.jar")}`
1500
1847
  ] : [],
1501
1848
  "-language-version",
1502
1849
  language,
@@ -1509,59 +1856,70 @@ async function compileKotlin(input, origin) {
1509
1856
  "-ir-output-name",
1510
1857
  "app",
1511
1858
  ...compiledSources.map(({ target }) => target),
1512
- ...Object.keys(generated).map((name) => import_node_path5.default.join(generatedDir, name))
1859
+ ...Object.keys(generated).map((name) => import_node_path7.default.join(generatedDir, name))
1513
1860
  ],
1514
1861
  { maxBuffer: 16 * 1024 * 1024 }
1515
1862
  );
1516
1863
  try {
1864
+ if (java)
1865
+ await compileJavaModuleAbi({
1866
+ specs: java,
1867
+ work,
1868
+ hash,
1869
+ toolchain: ready,
1870
+ libraries: libraries.filter((library) => library !== javaLibrary),
1871
+ sdkRoot: sdk.root,
1872
+ sdkLibrary,
1873
+ language
1874
+ });
1517
1875
  if (viewModels && inputs.some(
1518
1876
  ({ file, bytes }) => sources.includes(file) && bytes.includes("ViewModel")
1519
1877
  )) {
1520
- await compileKlib(import_node_path5.default.join(work, "abi"));
1521
- const { stdout } = await run3(
1522
- import_node_path5.default.join(import_node_path5.default.dirname(kotlinc), "kotlin"),
1878
+ await compileKlib(import_node_path7.default.join(work, "abi"));
1879
+ const { stdout } = await run5(
1880
+ import_node_path7.default.join(import_node_path7.default.dirname(kotlinc), "kotlin"),
1523
1881
  [
1524
1882
  "-cp",
1525
1883
  [
1526
- import_node_path5.default.resolve(import_node_path5.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
1527
- import_node_path5.default.join(sdk.root, "tools.jar")
1528
- ].join(import_node_path5.default.delimiter),
1884
+ import_node_path7.default.resolve(import_node_path7.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
1885
+ import_node_path7.default.join(sdk.root, "tools.jar")
1886
+ ].join(import_node_path7.default.delimiter),
1529
1887
  viewModels.toolClass,
1530
- import_node_path5.default.join(work, "abi")
1888
+ import_node_path7.default.join(work, "abi")
1531
1889
  ],
1532
1890
  { maxBuffer: 64 * 1024 * 1024 }
1533
1891
  );
1534
- import_node_fs4.default.writeFileSync(
1535
- import_node_path5.default.join(generatedDir, viewModels.file),
1892
+ import_node_fs6.default.writeFileSync(
1893
+ import_node_path7.default.join(generatedDir, viewModels.file),
1536
1894
  viewModels.render(viewModelClasses(readAbiClasses(stdout)))
1537
1895
  );
1538
1896
  }
1539
- await compileKlib(import_node_path5.default.join(work, "klib"));
1540
- await run3(
1897
+ await compileKlib(import_node_path7.default.join(work, "klib"));
1898
+ await run5(
1541
1899
  kotlinc,
1542
1900
  [
1543
1901
  ...common,
1544
1902
  "-nowarn",
1545
- `-Xinclude=${import_node_path5.default.join(work, "klib")}`,
1903
+ `-Xinclude=${import_node_path7.default.join(work, "klib")}`,
1546
1904
  "-Xir-produce-js",
1547
1905
  "-ir-output-dir",
1548
- import_node_path5.default.join(work, "js"),
1906
+ import_node_path7.default.join(work, "js"),
1549
1907
  "-ir-output-name",
1550
1908
  "app"
1551
1909
  ],
1552
1910
  { maxBuffer: 16 * 1024 * 1024 }
1553
1911
  );
1554
1912
  if (usesCompose) {
1555
- await run3("unzip", [
1913
+ await run5("unzip", [
1556
1914
  "-q",
1557
1915
  "-j",
1558
1916
  composeRuntime,
1559
1917
  "skiko.mjs",
1560
1918
  "-d",
1561
- import_node_path5.default.join(work, "js")
1919
+ import_node_path7.default.join(work, "js")
1562
1920
  ]);
1563
- const skikoPath = import_node_path5.default.join(work, "js", "skiko.mjs");
1564
- const upstream = (0, import_acorn2.parse)(import_node_fs4.default.readFileSync(skikoPath, "utf8"), {
1921
+ const skikoPath = import_node_path7.default.join(work, "js", "skiko.mjs");
1922
+ const upstream = (0, import_acorn2.parse)(import_node_fs6.default.readFileSync(skikoPath, "utf8"), {
1565
1923
  ecmaVersion: "latest",
1566
1924
  sourceType: "module"
1567
1925
  });
@@ -1584,7 +1942,7 @@ async function compileKotlin(input, origin) {
1584
1942
  "GL",
1585
1943
  ...bindings
1586
1944
  ];
1587
- import_node_fs4.default.writeFileSync(
1945
+ import_node_fs6.default.writeFileSync(
1588
1946
  skikoPath,
1589
1947
  [
1590
1948
  "const runtime = globalThis.__peachKotlinSkiko;",
@@ -1598,10 +1956,10 @@ async function compileKotlin(input, origin) {
1598
1956
  if (usesCompose) {
1599
1957
  for (const library of toolchain.composeJsLibraries) {
1600
1958
  let imported = false;
1601
- for (const file of import_node_fs4.default.readdirSync(import_node_path5.default.join(work, "js"))) {
1959
+ for (const file of import_node_fs6.default.readdirSync(import_node_path7.default.join(work, "js"))) {
1602
1960
  if (!file.endsWith(".mjs")) continue;
1603
- const target = import_node_path5.default.join(work, "js", file);
1604
- const source = import_node_fs4.default.readFileSync(target, "utf8");
1961
+ const target = import_node_path7.default.join(work, "js", file);
1962
+ const source = import_node_fs6.default.readFileSync(target, "utf8");
1605
1963
  let next = source;
1606
1964
  for (const quote of ["'", '"'])
1607
1965
  next = next.replaceAll(
@@ -1609,29 +1967,34 @@ async function compileKotlin(input, origin) {
1609
1967
  `from ${quote}./${library.file}${quote}`
1610
1968
  );
1611
1969
  if (next === source) continue;
1612
- import_node_fs4.default.writeFileSync(target, next);
1970
+ import_node_fs6.default.writeFileSync(target, next);
1613
1971
  imported = true;
1614
1972
  }
1615
1973
  if (!imported) continue;
1616
- const archive = import_node_path5.default.join(
1974
+ const archive = import_node_path7.default.join(
1617
1975
  kotlinHome(),
1618
1976
  toolchain.compiler.version,
1619
1977
  library.name
1620
1978
  );
1621
1979
  await fetchVerified(library, archive);
1622
- const { stdout } = await run3("tar", ["-xOf", archive, library.archiveEntry], {
1980
+ const { stdout } = await run5("tar", ["-xOf", archive, library.archiveEntry], {
1623
1981
  maxBuffer: 16 * 1024 * 1024
1624
1982
  });
1625
- import_node_fs4.default.writeFileSync(import_node_path5.default.join(work, "js", library.file), stdout);
1983
+ import_node_fs6.default.writeFileSync(import_node_path7.default.join(work, "js", library.file), stdout);
1626
1984
  }
1627
1985
  }
1628
1986
  } catch (error) {
1629
- import_node_fs4.default.rmSync(work, { recursive: true, force: true });
1987
+ import_node_fs6.default.rmSync(work, { recursive: true, force: true });
1630
1988
  let output = isRecord(error) ? `${String(error.stderr ?? "")}${String(error.stdout ?? "")}` : "";
1631
1989
  for (const [name, source] of Object.entries(origins))
1632
- output = output.replaceAll(import_node_path5.default.join(generatedDir, name), source);
1990
+ output = output.replaceAll(import_node_path7.default.join(generatedDir, name), source);
1633
1991
  for (const { file, target } of compiledSources)
1634
- output = output.replaceAll(target, file).replaceAll(import_node_path5.default.relative(process.cwd(), target), file);
1992
+ output = output.replaceAll(target, file).replaceAll(import_node_path7.default.relative(process.cwd(), target), file);
1993
+ for (const [index, spec] of (java?.specs ?? []).entries())
1994
+ output = output.replaceAll(
1995
+ import_node_path7.default.join(work, "java-abi", `Spec${index}.kt`),
1996
+ spec.file
1997
+ );
1635
1998
  throw new Error(
1636
1999
  `kotlin compile failed:
1637
2000
  ${output.trim() || (error instanceof Error ? error.message : String(error))}`
@@ -1640,9 +2003,9 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1640
2003
  const seams = [
1641
2004
  ["process.release.name", "process.release?.name"]
1642
2005
  ];
1643
- const js = import_node_fs4.default.readdirSync(import_node_path5.default.join(work, "js")).filter((file) => file.endsWith(".mjs"));
2006
+ const js = import_node_fs6.default.readdirSync(import_node_path7.default.join(work, "js")).filter((file) => file.endsWith(".mjs"));
1644
2007
  if (js.some(
1645
- (file) => import_node_fs4.default.readFileSync(import_node_path5.default.join(work, "js", file), "utf8").includes("'kotlinx.coroutines.")
2008
+ (file) => import_node_fs6.default.readFileSync(import_node_path7.default.join(work, "js", file), "utf8").includes("'kotlinx.coroutines.")
1646
2009
  ))
1647
2010
  seams.push([
1648
2011
  "(typeof(window) !== 'undefined' && window != null && typeof(window.addEventListener) === 'function') ? window : null",
@@ -1651,12 +2014,12 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1651
2014
  for (const [from, to] of seams) {
1652
2015
  let patched = 0;
1653
2016
  for (const file of js) {
1654
- const target = import_node_path5.default.join(work, "js", file);
1655
- const text = import_node_fs4.default.readFileSync(target, "utf8");
2017
+ const target = import_node_path7.default.join(work, "js", file);
2018
+ const text = import_node_fs6.default.readFileSync(target, "utf8");
1656
2019
  const next = text.replaceAll(from, to);
1657
2020
  if (next !== text) {
1658
2021
  patched++;
1659
- import_node_fs4.default.writeFileSync(target, next);
2022
+ import_node_fs6.default.writeFileSync(target, next);
1660
2023
  }
1661
2024
  }
1662
2025
  if (patched === 0)
@@ -1664,11 +2027,11 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1664
2027
  `kotlin output no longer contains ${from}; recheck how it detects its host in Peach`
1665
2028
  );
1666
2029
  }
1667
- const entry = import_node_path5.default.join(work, "js/app.mjs");
1668
- const entrySource2 = import_node_fs4.default.readFileSync(entry, "utf8");
1669
- const importsPath = import_node_path5.default.join(work, "js/app.import-object.mjs");
2030
+ const entry = import_node_path7.default.join(work, "js/app.mjs");
2031
+ const entrySource2 = import_node_fs6.default.readFileSync(entry, "utf8");
2032
+ const importsPath = import_node_path7.default.join(work, "js/app.import-object.mjs");
1670
2033
  const importsFactory = kotlinInstanceSource(
1671
- import_node_fs4.default.readFileSync(importsPath, "utf8"),
2034
+ import_node_fs6.default.readFileSync(importsPath, "utf8"),
1672
2035
  "createKotlinImportObject"
1673
2036
  );
1674
2037
  const runtimeFactory = kotlinInstanceSource(
@@ -1676,9 +2039,9 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1676
2039
  "createKotlinInstance",
1677
2040
  /* @__PURE__ */ new Map([["./app.import-object.mjs", "createKotlinImportObject"]])
1678
2041
  );
1679
- import_node_fs4.default.writeFileSync(importsPath, importsFactory.source);
1680
- import_node_fs4.default.writeFileSync(import_node_path5.default.join(work, "js/app-runtime.mjs"), runtimeFactory.source);
1681
- import_node_fs4.default.writeFileSync(
2042
+ import_node_fs6.default.writeFileSync(importsPath, importsFactory.source);
2043
+ import_node_fs6.default.writeFileSync(import_node_path7.default.join(work, "js/app-runtime.mjs"), runtimeFactory.source);
2044
+ import_node_fs6.default.writeFileSync(
1682
2045
  entry,
1683
2046
  [
1684
2047
  "import { createKotlinInstance } from './app-runtime.mjs';",
@@ -1691,10 +2054,10 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1691
2054
  ].join("\n")
1692
2055
  );
1693
2056
  try {
1694
- import_node_fs4.default.renameSync(work, out);
2057
+ import_node_fs6.default.renameSync(work, out);
1695
2058
  } catch (error) {
1696
- if (!import_node_fs4.default.existsSync(import_node_path5.default.join(out, "js", "app.wasm"))) throw error;
1697
- import_node_fs4.default.rmSync(work, { recursive: true, force: true });
2059
+ if (!import_node_fs6.default.existsSync(import_node_path7.default.join(out, "js", "app.wasm"))) throw error;
2060
+ import_node_fs6.default.rmSync(work, { recursive: true, force: true });
1698
2061
  }
1699
2062
  return artifact;
1700
2063
  })().finally(() => builds.delete(hash));
@@ -1706,24 +2069,24 @@ var CONTENT_TYPES = {
1706
2069
  ".wasm": "application/wasm"
1707
2070
  };
1708
2071
  function kotlinArtifactFiles(hash) {
1709
- const dir = import_node_path5.default.join(buildsDir(), hash, "js");
1710
- return import_node_fs4.default.readdirSync(dir).sort().map((name) => {
1711
- const contentType = CONTENT_TYPES[import_node_path5.default.extname(name)];
2072
+ const dir = import_node_path7.default.join(buildsDir(), hash, "js");
2073
+ return import_node_fs6.default.readdirSync(dir).sort().map((name) => {
2074
+ const contentType = CONTENT_TYPES[import_node_path7.default.extname(name)];
1712
2075
  if (!contentType) throw new Error(`unexpected kotlin artifact file ${name}`);
1713
- return { name, bytes: import_node_fs4.default.readFileSync(import_node_path5.default.join(dir, name)), contentType };
2076
+ return { name, bytes: import_node_fs6.default.readFileSync(import_node_path7.default.join(dir, name)), contentType };
1714
2077
  });
1715
2078
  }
1716
2079
  function serveKotlinArtifact(pathname, res) {
1717
2080
  if (!pathname.startsWith(KOTLIN_ARTIFACT_PREFIX)) return false;
1718
2081
  const [hash, file, ...rest] = pathname.slice(KOTLIN_ARTIFACT_PREFIX.length).split("/");
1719
- const type = file ? CONTENT_TYPES[import_node_path5.default.extname(file)] : void 0;
2082
+ const type = file ? CONTENT_TYPES[import_node_path7.default.extname(file)] : void 0;
1720
2083
  if (!hash || !/^[0-9a-f]+$/.test(hash) || !file || rest.length > 0 || !type || file.includes("..")) {
1721
2084
  res.statusCode = 404;
1722
2085
  res.end("not a kotlin artifact");
1723
2086
  return true;
1724
2087
  }
1725
- const target = import_node_path5.default.join(buildsDir(), hash, "js", file);
1726
- if (!import_node_fs4.default.existsSync(target)) {
2088
+ const target = import_node_path7.default.join(buildsDir(), hash, "js", file);
2089
+ if (!import_node_fs6.default.existsSync(target)) {
1727
2090
  res.statusCode = 404;
1728
2091
  res.end(`kotlin artifact ${hash}/${file} was not built`);
1729
2092
  return true;
@@ -1731,7 +2094,7 @@ function serveKotlinArtifact(pathname, res) {
1731
2094
  res.setHeader("access-control-allow-origin", "*");
1732
2095
  res.setHeader("content-type", type);
1733
2096
  res.setHeader("cache-control", "public, max-age=31536000, immutable");
1734
- res.end(import_node_fs4.default.readFileSync(target));
2097
+ res.end(import_node_fs6.default.readFileSync(target));
1735
2098
  return true;
1736
2099
  }
1737
2100
  var KOTLIN_PACKAGE_PATH = "/__peach/kotlin-package";