peachsim 0.1.2186 → 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 (93) hide show
  1. package/dist-lib/agent-daemon-client.cjs +1 -1
  2. package/dist-lib/agent-events.cjs +1 -1
  3. package/dist-lib/attached-projects.cjs +1 -1
  4. package/dist-lib/auth/shared-session.cjs +1 -1
  5. package/dist-lib/backend-origin.cjs +1 -1
  6. package/dist-lib/beta.cjs +1 -1
  7. package/dist-lib/beta.mjs +1 -1
  8. package/dist-lib/bridge-constants.cjs +1 -1
  9. package/dist-lib/bridge-contract-input.cjs +1 -1
  10. package/dist-lib/bridge-contract-input.mjs +1 -1
  11. package/dist-lib/bridge-contract.cjs +1 -1
  12. package/dist-lib/bridge-contract.mjs +1 -1
  13. package/dist-lib/bundle-channel.cjs +2706 -2381
  14. package/dist-lib/capture-contract.cjs +1 -1
  15. package/dist-lib/capture-contract.mjs +1 -1
  16. package/dist-lib/cloud-contract.cjs +1 -1
  17. package/dist-lib/cloud-contract.mjs +1 -1
  18. package/dist-lib/cloud-test-args.cjs +1 -1
  19. package/dist-lib/cloud-test-args.mjs +1 -1
  20. package/dist-lib/cloud.cjs +1 -1
  21. package/dist-lib/cloud.mjs +1 -1
  22. package/dist-lib/config.cjs +1 -1
  23. package/dist-lib/config.mjs +1 -1
  24. package/dist-lib/detox/index.cjs +1 -1
  25. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  26. package/dist-lib/expo-swift-bundle.cjs +3227 -3220
  27. package/dist-lib/expo-swift-metadata.cjs +1 -1
  28. package/dist-lib/expo-swift-metadata.mjs +1 -1
  29. package/dist-lib/home-paths.cjs +1 -1
  30. package/dist-lib/host/bridge-host.cjs +4538 -4213
  31. package/dist-lib/host/fetch-proxy-handler.cjs +6 -5
  32. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  34. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  35. package/dist-lib/host/websocket-proxy.cjs +1 -1
  36. package/dist-lib/index.cjs +429 -279
  37. package/dist-lib/jump-to-source-babel.cjs +1 -1
  38. package/dist-lib/jump-to-source-native.cjs +1 -1
  39. package/dist-lib/kotlin-host.cjs +645 -284
  40. package/dist-lib/menu.cjs +1 -1
  41. package/dist-lib/menu.mjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  43. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  44. package/dist-lib/metro-production-bundle.cjs +1 -1
  45. package/dist-lib/metro-production-bundle.mjs +1 -1
  46. package/dist-lib/metro.cjs +730 -580
  47. package/dist-lib/native-app-identity-project.cjs +2 -2
  48. package/dist-lib/native-app-identity-project.mjs +2 -2
  49. package/dist-lib/native-app-identity.cjs +1 -1
  50. package/dist-lib/native-app-identity.mjs +1 -1
  51. package/dist-lib/native-firebase-metadata.cjs +1 -1
  52. package/dist-lib/native-firebase-metadata.mjs +1 -1
  53. package/dist-lib/pdfium-raster.cjs +1 -1
  54. package/dist-lib/pdfium-raster.mjs +1 -1
  55. package/dist-lib/plist.cjs +1 -1
  56. package/dist-lib/plist.mjs +1 -1
  57. package/dist-lib/profiles.cjs +1 -1
  58. package/dist-lib/public-brand.cjs +1 -1
  59. package/dist-lib/public-origins-lib-esm.json +24 -24
  60. package/dist-lib/public-origins-lib.json +99 -59
  61. package/dist-lib/react-native-host-modules.cjs +1 -1
  62. package/dist-lib/react-native-host-modules.mjs +1 -1
  63. package/dist-lib/reap-browser.cjs +1 -1
  64. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  65. package/dist-lib/sdk.cjs +1 -1
  66. package/dist-lib/sdk.mjs +1 -1
  67. package/dist-lib/skills.cjs +5196 -4871
  68. package/dist-lib/swift-compile.cjs +2 -2
  69. package/dist-lib/swift-compile.mjs +2 -2
  70. package/dist-lib/swift-package.cjs +1 -1
  71. package/dist-lib/swift-package.mjs +1 -1
  72. package/dist-lib/swift-submit.cjs +1 -1
  73. package/dist-lib/swift-submit.mjs +1 -1
  74. package/dist-lib/swift-toolchain.cjs +1 -1
  75. package/dist-lib/swift.cjs +1 -1
  76. package/dist-lib/vite-swift.cjs +2 -2
  77. package/dist-lib/vite.cjs +6 -5
  78. package/dist-lib/worklet-executable.cjs +1 -1
  79. package/dist-lib/worklet-executable.mjs +1 -1
  80. package/kotlin/sdk.tar.gz +0 -0
  81. package/package.json +1 -1
  82. package/sdk/ios/System/Library/Frameworks/CFNetwork.framework/Headers/CFNetwork.h +10 -0
  83. package/src/android-autolinking.ts +45 -4
  84. package/src/android-bridge-packages.ts +2 -2
  85. package/src/android-gradle-sources.ts +143 -0
  86. package/src/androidAutolinkingContract.ts +8 -0
  87. package/src/androidGradleContract.ts +14 -0
  88. package/src/expo-kotlin-host.ts +3 -0
  89. package/src/java-module-abi.ts +145 -0
  90. package/src/javaAbiContract.ts +14 -0
  91. package/src/kotlin-host.ts +55 -3
  92. package/src/nitro-source.ts +2 -167
  93. package/src/react-native-autolinking.ts +153 -0
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2186 | (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,11 +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, settings: 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)",
651
968
  " dev.peach.android.ProcessSettings.configure(settings)",
969
+ " android.os.SystemProperties.configure(properties)",
652
970
  "}",
653
971
  "",
654
972
  "@OptIn(kotlin.js.ExperimentalJsExport::class, kotlinx.coroutines.DelicateCoroutinesApi::class)",
@@ -679,7 +997,7 @@ function entrySource(ids) {
679
997
  var BUILD_FORMAT = 19;
680
998
  var builds = /* @__PURE__ */ new Map();
681
999
  function buildsDir() {
682
- return import_node_path5.default.join(kotlinHome(), "builds");
1000
+ return import_node_path7.default.join(kotlinHome(), "builds");
683
1001
  }
684
1002
  async function kotlinArtifact(root, moduleRoot, origin, target = "app") {
685
1003
  const { kotlinSourceId, nativeSourceContract, renderKotlinSourceGlue } = await import("vxrn/native-source-contract");
@@ -692,7 +1010,7 @@ async function kotlinArtifact(root, moduleRoot, origin, target = "app") {
692
1010
  const viewIds = [];
693
1011
  let usesCompose = false;
694
1012
  for (const file of sources) {
695
- const source = import_node_fs4.default.readFileSync(file, "utf8");
1013
+ const source = import_node_fs6.default.readFileSync(file, "utf8");
696
1014
  if (/\bandroidx\.compose\./.test(source)) usesCompose = true;
697
1015
  const contract = nativeSourceContract(file, source);
698
1016
  if (contract.modules.length === 0 && contract.views.length === 0) continue;
@@ -782,24 +1100,24 @@ function readExpoTypes(output) {
782
1100
  }
783
1101
  var toolScans = /* @__PURE__ */ new Map();
784
1102
  async function scanSources(tool, parse3, toolchain, moduleRoot, files) {
785
- 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));
786
1104
  const sdk = await loadKotlinSdk(moduleRoot, toolchain);
787
- 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")));
788
1106
  digest.update(tool);
789
- 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`);
790
1108
  const key = digest.digest("hex");
791
1109
  let scan = toolScans.get(key);
792
1110
  if (!scan) {
793
1111
  scan = (async () => {
794
1112
  const { kotlinc } = await ensureToolchain(toolchain);
795
- const { stdout } = await run3(
796
- 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"),
797
1115
  [
798
1116
  "-cp",
799
1117
  [
800
- import_node_path5.default.resolve(import_node_path5.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
801
- import_node_path5.default.join(sdk.root, "tools.jar")
802
- ].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),
803
1121
  tool,
804
1122
  ...files
805
1123
  ],
@@ -817,7 +1135,7 @@ async function scanSources(tool, parse3, toolchain, moduleRoot, files) {
817
1135
  async function scanExpoTypes(toolchain, moduleRoot, sources) {
818
1136
  const candidates = sources.filter(
819
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(
820
- import_node_fs4.default.readFileSync(file, "utf8")
1138
+ import_node_fs6.default.readFileSync(file, "utf8")
821
1139
  )
822
1140
  );
823
1141
  if (candidates.length === 0) return [];
@@ -1006,7 +1324,7 @@ function expoTypeSources(files) {
1006
1324
  )
1007
1325
  ];
1008
1326
  if (edits.length > 0 || views.length > 0) {
1009
- 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");
1010
1328
  for (const { range, owner, field } of edits.sort((a, b) => b.range[0] - a.range[0]))
1011
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])}`;
1012
1330
  if (views.length > 0) {
@@ -1022,7 +1340,7 @@ function expoTypeSources(files) {
1022
1340
  `${file.package ? `${file.package}.` : ""}peachExpoViews${index}()`
1023
1341
  );
1024
1342
  }
1025
- const name = `PeachExpoSource_${index}_${import_node_path5.default.basename(file.file)}`;
1343
+ const name = `PeachExpoSource_${index}_${import_node_path7.default.basename(file.file)}`;
1026
1344
  generated[name] = text;
1027
1345
  origins[name] = file.file;
1028
1346
  }
@@ -1041,11 +1359,30 @@ function expoTypeSources(files) {
1041
1359
  return { generated, origins, registrations };
1042
1360
  }
1043
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
+ }
1044
1381
  const toolchain = readToolchain(moduleRoot);
1045
1382
  const language = appKotlinLanguage(root);
1046
1383
  const scanned = await scanExpoTypes(toolchain, moduleRoot, modules.sources);
1047
1384
  const usesCompose = scanned.some((file) => file.views.length > 0) || modules.sources.some(
1048
- (file) => /\bandroidx\.compose\./.test(import_node_fs4.default.readFileSync(file, "utf8"))
1385
+ (file) => /\bandroidx\.compose\./.test(import_node_fs6.default.readFileSync(file, "utf8"))
1049
1386
  );
1050
1387
  const types = expoTypeSources(scanned);
1051
1388
  const rewritten = new Set(Object.values(types.origins));
@@ -1064,11 +1401,12 @@ async function expoKotlinArtifact(root, moduleRoot, origin, modules) {
1064
1401
  " ))",
1065
1402
  "}",
1066
1403
  "",
1067
- "@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String) {",
1404
+ "@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String, properties: String) {",
1068
1405
  " android.os.Build.setDevice(model, release, apiLevel)",
1069
1406
  " java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))",
1070
1407
  " java.util.TimeZone.setDevice(timeZone)",
1071
1408
  " dev.peach.android.ProcessSettings.configure(settings)",
1409
+ " android.os.SystemProperties.configure(properties)",
1072
1410
  " PeachExpoRuntime.configureProcessLocale(locale)",
1073
1411
  "}",
1074
1412
  "",
@@ -1090,6 +1428,7 @@ async function expoKotlinArtifact(root, moduleRoot, origin, modules) {
1090
1428
  toolchain,
1091
1429
  language,
1092
1430
  sources: modules.sources.filter((file) => !rewritten.has(file)),
1431
+ javaSpecs: modules.javaSpecs,
1093
1432
  generated: {
1094
1433
  ...types.generated,
1095
1434
  "PeachExpoEntry.kt": entry,
@@ -1270,7 +1609,7 @@ function appResourceSources(app) {
1270
1609
  entries: app.drawables.map((drawable) => ({
1271
1610
  name: drawable.name,
1272
1611
  init: `listOf(
1273
- ${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")}
1274
1613
  )`
1275
1614
  }))
1276
1615
  },
@@ -1339,7 +1678,7 @@ function drawableInit(drawable, file) {
1339
1678
  if (drawable.kind === "xml") return `PeachDrawable.Xml(${where})`;
1340
1679
  if (drawable.kind === "bitmap")
1341
1680
  return `PeachDrawable.Bitmap(${where}, ${drawable.ninePatch}, ${literal(
1342
- import_node_fs4.default.readFileSync(drawable.file).toString("base64")
1681
+ import_node_fs6.default.readFileSync(drawable.file).toString("base64")
1343
1682
  )})`;
1344
1683
  const vector = drawable.vector;
1345
1684
  const float = (value) => `${value}f`;
@@ -1399,11 +1738,13 @@ async function compileKotlin(input, origin) {
1399
1738
  sdkProfile,
1400
1739
  usesCompose,
1401
1740
  usesSerialization = false,
1402
- viewModels
1741
+ viewModels,
1742
+ javaSpecs = []
1403
1743
  } = input;
1404
1744
  const sdk = await loadKotlinSdk(moduleRoot, toolchain);
1405
- const plugin = import_node_path5.default.join(sdk.root, "plugin.jar");
1406
- 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;
1407
1748
  const generated = {
1408
1749
  ...sourceGenerated,
1409
1750
  "PeachBindingsInitialization.kt": [
@@ -1415,6 +1756,7 @@ async function compileKotlin(input, origin) {
1415
1756
  "@JsExport fun peachInitializeModuleBindings() {",
1416
1757
  " if (!initialized) {",
1417
1758
  " requireIncomingBindings()",
1759
+ ...java ? [` ${JAVA_BINDINGS_INITIALIZER}()`] : [],
1418
1760
  " initializeApplicationIncomingBindings()",
1419
1761
  ...sourceGenerated["PeachViews.kt"] ? [" initializeApplicationViews()"] : [],
1420
1762
  " initialized = true",
@@ -1424,9 +1766,9 @@ async function compileKotlin(input, origin) {
1424
1766
  };
1425
1767
  const inputs = sources.map((file) => ({
1426
1768
  file,
1427
- bytes: import_node_fs4.default.readFileSync(file)
1769
+ bytes: import_node_fs6.default.readFileSync(file)
1428
1770
  }));
1429
- const digest = (0, import_node_crypto4.createHash)("sha256");
1771
+ const digest = (0, import_node_crypto6.createHash)("sha256");
1430
1772
  digest.update(
1431
1773
  JSON.stringify({
1432
1774
  format: BUILD_FORMAT,
@@ -1434,11 +1776,12 @@ async function compileKotlin(input, origin) {
1434
1776
  language,
1435
1777
  sdk: sdk.sha256,
1436
1778
  sdkProfile,
1437
- usesSerialization
1779
+ usesSerialization,
1780
+ java: java?.sha256
1438
1781
  })
1439
1782
  );
1440
1783
  for (const { file, bytes } of inputs)
1441
- 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");
1442
1785
  if (viewModels) digest.update(viewModels.toolClass);
1443
1786
  for (const [name, text] of Object.entries(generated))
1444
1787
  digest.update(`${name}\0${text}\0`);
@@ -1447,37 +1790,39 @@ async function compileKotlin(input, origin) {
1447
1790
  url: `${origin}${KOTLIN_ARTIFACT_PREFIX}${hash}/app.mjs`,
1448
1791
  hash
1449
1792
  };
1450
- const out = import_node_path5.default.join(buildsDir(), hash);
1451
- 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;
1452
1795
  const pending = builds.get(hash);
1453
1796
  if (pending) return pending;
1454
1797
  const build = (async () => {
1455
1798
  const ready = await ensureToolchain(toolchain);
1456
1799
  const { kotlinc } = ready;
1457
1800
  const libraries = [...ready.libraries, sdkLibrary];
1458
- const composeRuntime = import_node_path5.default.join(
1801
+ const composeRuntime = import_node_path7.default.join(
1459
1802
  kotlinHome(),
1460
1803
  toolchain.compiler.version,
1461
1804
  toolchain.composeRuntime.name
1462
1805
  );
1463
1806
  if (usesCompose) {
1464
1807
  for (const library of toolchain.composeLibraries) {
1465
- 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);
1466
1809
  await fetchVerified(library, target);
1467
1810
  libraries.push(target);
1468
1811
  }
1469
1812
  await fetchVerified(toolchain.composeRuntime, composeRuntime);
1470
1813
  }
1471
- import_node_fs4.default.mkdirSync(buildsDir(), { recursive: true });
1472
- const work = import_node_fs4.default.mkdtempSync(import_node_path5.default.join(buildsDir(), `${hash}-`));
1473
- const generatedDir = import_node_path5.default.join(work, "generated");
1474
- 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);
1475
1820
  for (const [name, text] of Object.entries(generated))
1476
- 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);
1477
1822
  const compiledSources = inputs.map(({ file, bytes }, index) => {
1478
- const target = import_node_path5.default.join(work, "sources", String(index), import_node_path5.default.basename(file));
1479
- import_node_fs4.default.mkdirSync(import_node_path5.default.dirname(target), { recursive: true });
1480
- 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);
1481
1826
  return { file, target };
1482
1827
  });
1483
1828
  const common = [
@@ -1486,19 +1831,19 @@ async function compileKotlin(input, origin) {
1486
1831
  "-Xallow-kotlin-package",
1487
1832
  "-Xwasm-target=js",
1488
1833
  "-libraries",
1489
- libraries.join(import_node_path5.default.delimiter)
1834
+ libraries.join(import_node_path7.default.delimiter)
1490
1835
  ];
1491
- const compileKlib = (outputDir) => run3(
1836
+ const compileKlib = (outputDir) => run5(
1492
1837
  kotlinc,
1493
1838
  [
1494
1839
  ...common,
1495
1840
  `-Xplugin=${plugin}`,
1496
- `-Xfriend-modules=${sdkLibrary}`,
1841
+ `-Xfriend-modules=${[sdkLibrary, ...javaLibrary ? [javaLibrary] : []].join(import_node_path7.default.delimiter)}`,
1497
1842
  ...usesCompose ? [
1498
- `-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")}`
1499
1844
  ] : [],
1500
1845
  ...usesSerialization ? [
1501
- `-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")}`
1502
1847
  ] : [],
1503
1848
  "-language-version",
1504
1849
  language,
@@ -1511,59 +1856,70 @@ async function compileKotlin(input, origin) {
1511
1856
  "-ir-output-name",
1512
1857
  "app",
1513
1858
  ...compiledSources.map(({ target }) => target),
1514
- ...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))
1515
1860
  ],
1516
1861
  { maxBuffer: 16 * 1024 * 1024 }
1517
1862
  );
1518
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
+ });
1519
1875
  if (viewModels && inputs.some(
1520
1876
  ({ file, bytes }) => sources.includes(file) && bytes.includes("ViewModel")
1521
1877
  )) {
1522
- await compileKlib(import_node_path5.default.join(work, "abi"));
1523
- const { stdout } = await run3(
1524
- 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"),
1525
1881
  [
1526
1882
  "-cp",
1527
1883
  [
1528
- import_node_path5.default.resolve(import_node_path5.default.dirname(kotlinc), "../lib/kotlin-compiler.jar"),
1529
- import_node_path5.default.join(sdk.root, "tools.jar")
1530
- ].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),
1531
1887
  viewModels.toolClass,
1532
- import_node_path5.default.join(work, "abi")
1888
+ import_node_path7.default.join(work, "abi")
1533
1889
  ],
1534
1890
  { maxBuffer: 64 * 1024 * 1024 }
1535
1891
  );
1536
- import_node_fs4.default.writeFileSync(
1537
- import_node_path5.default.join(generatedDir, viewModels.file),
1892
+ import_node_fs6.default.writeFileSync(
1893
+ import_node_path7.default.join(generatedDir, viewModels.file),
1538
1894
  viewModels.render(viewModelClasses(readAbiClasses(stdout)))
1539
1895
  );
1540
1896
  }
1541
- await compileKlib(import_node_path5.default.join(work, "klib"));
1542
- await run3(
1897
+ await compileKlib(import_node_path7.default.join(work, "klib"));
1898
+ await run5(
1543
1899
  kotlinc,
1544
1900
  [
1545
1901
  ...common,
1546
1902
  "-nowarn",
1547
- `-Xinclude=${import_node_path5.default.join(work, "klib")}`,
1903
+ `-Xinclude=${import_node_path7.default.join(work, "klib")}`,
1548
1904
  "-Xir-produce-js",
1549
1905
  "-ir-output-dir",
1550
- import_node_path5.default.join(work, "js"),
1906
+ import_node_path7.default.join(work, "js"),
1551
1907
  "-ir-output-name",
1552
1908
  "app"
1553
1909
  ],
1554
1910
  { maxBuffer: 16 * 1024 * 1024 }
1555
1911
  );
1556
1912
  if (usesCompose) {
1557
- await run3("unzip", [
1913
+ await run5("unzip", [
1558
1914
  "-q",
1559
1915
  "-j",
1560
1916
  composeRuntime,
1561
1917
  "skiko.mjs",
1562
1918
  "-d",
1563
- import_node_path5.default.join(work, "js")
1919
+ import_node_path7.default.join(work, "js")
1564
1920
  ]);
1565
- const skikoPath = import_node_path5.default.join(work, "js", "skiko.mjs");
1566
- 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"), {
1567
1923
  ecmaVersion: "latest",
1568
1924
  sourceType: "module"
1569
1925
  });
@@ -1586,7 +1942,7 @@ async function compileKotlin(input, origin) {
1586
1942
  "GL",
1587
1943
  ...bindings
1588
1944
  ];
1589
- import_node_fs4.default.writeFileSync(
1945
+ import_node_fs6.default.writeFileSync(
1590
1946
  skikoPath,
1591
1947
  [
1592
1948
  "const runtime = globalThis.__peachKotlinSkiko;",
@@ -1600,10 +1956,10 @@ async function compileKotlin(input, origin) {
1600
1956
  if (usesCompose) {
1601
1957
  for (const library of toolchain.composeJsLibraries) {
1602
1958
  let imported = false;
1603
- 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"))) {
1604
1960
  if (!file.endsWith(".mjs")) continue;
1605
- const target = import_node_path5.default.join(work, "js", file);
1606
- 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");
1607
1963
  let next = source;
1608
1964
  for (const quote of ["'", '"'])
1609
1965
  next = next.replaceAll(
@@ -1611,29 +1967,34 @@ async function compileKotlin(input, origin) {
1611
1967
  `from ${quote}./${library.file}${quote}`
1612
1968
  );
1613
1969
  if (next === source) continue;
1614
- import_node_fs4.default.writeFileSync(target, next);
1970
+ import_node_fs6.default.writeFileSync(target, next);
1615
1971
  imported = true;
1616
1972
  }
1617
1973
  if (!imported) continue;
1618
- const archive = import_node_path5.default.join(
1974
+ const archive = import_node_path7.default.join(
1619
1975
  kotlinHome(),
1620
1976
  toolchain.compiler.version,
1621
1977
  library.name
1622
1978
  );
1623
1979
  await fetchVerified(library, archive);
1624
- const { stdout } = await run3("tar", ["-xOf", archive, library.archiveEntry], {
1980
+ const { stdout } = await run5("tar", ["-xOf", archive, library.archiveEntry], {
1625
1981
  maxBuffer: 16 * 1024 * 1024
1626
1982
  });
1627
- 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);
1628
1984
  }
1629
1985
  }
1630
1986
  } catch (error) {
1631
- import_node_fs4.default.rmSync(work, { recursive: true, force: true });
1987
+ import_node_fs6.default.rmSync(work, { recursive: true, force: true });
1632
1988
  let output = isRecord(error) ? `${String(error.stderr ?? "")}${String(error.stdout ?? "")}` : "";
1633
1989
  for (const [name, source] of Object.entries(origins))
1634
- output = output.replaceAll(import_node_path5.default.join(generatedDir, name), source);
1990
+ output = output.replaceAll(import_node_path7.default.join(generatedDir, name), source);
1635
1991
  for (const { file, target } of compiledSources)
1636
- 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
+ );
1637
1998
  throw new Error(
1638
1999
  `kotlin compile failed:
1639
2000
  ${output.trim() || (error instanceof Error ? error.message : String(error))}`
@@ -1642,9 +2003,9 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1642
2003
  const seams = [
1643
2004
  ["process.release.name", "process.release?.name"]
1644
2005
  ];
1645
- 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"));
1646
2007
  if (js.some(
1647
- (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.")
1648
2009
  ))
1649
2010
  seams.push([
1650
2011
  "(typeof(window) !== 'undefined' && window != null && typeof(window.addEventListener) === 'function') ? window : null",
@@ -1653,12 +2014,12 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1653
2014
  for (const [from, to] of seams) {
1654
2015
  let patched = 0;
1655
2016
  for (const file of js) {
1656
- const target = import_node_path5.default.join(work, "js", file);
1657
- 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");
1658
2019
  const next = text.replaceAll(from, to);
1659
2020
  if (next !== text) {
1660
2021
  patched++;
1661
- import_node_fs4.default.writeFileSync(target, next);
2022
+ import_node_fs6.default.writeFileSync(target, next);
1662
2023
  }
1663
2024
  }
1664
2025
  if (patched === 0)
@@ -1666,11 +2027,11 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1666
2027
  `kotlin output no longer contains ${from}; recheck how it detects its host in Peach`
1667
2028
  );
1668
2029
  }
1669
- const entry = import_node_path5.default.join(work, "js/app.mjs");
1670
- const entrySource2 = import_node_fs4.default.readFileSync(entry, "utf8");
1671
- 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");
1672
2033
  const importsFactory = kotlinInstanceSource(
1673
- import_node_fs4.default.readFileSync(importsPath, "utf8"),
2034
+ import_node_fs6.default.readFileSync(importsPath, "utf8"),
1674
2035
  "createKotlinImportObject"
1675
2036
  );
1676
2037
  const runtimeFactory = kotlinInstanceSource(
@@ -1678,9 +2039,9 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1678
2039
  "createKotlinInstance",
1679
2040
  /* @__PURE__ */ new Map([["./app.import-object.mjs", "createKotlinImportObject"]])
1680
2041
  );
1681
- import_node_fs4.default.writeFileSync(importsPath, importsFactory.source);
1682
- import_node_fs4.default.writeFileSync(import_node_path5.default.join(work, "js/app-runtime.mjs"), runtimeFactory.source);
1683
- 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(
1684
2045
  entry,
1685
2046
  [
1686
2047
  "import { createKotlinInstance } from './app-runtime.mjs';",
@@ -1693,10 +2054,10 @@ ${output.trim() || (error instanceof Error ? error.message : String(error))}`
1693
2054
  ].join("\n")
1694
2055
  );
1695
2056
  try {
1696
- import_node_fs4.default.renameSync(work, out);
2057
+ import_node_fs6.default.renameSync(work, out);
1697
2058
  } catch (error) {
1698
- if (!import_node_fs4.default.existsSync(import_node_path5.default.join(out, "js", "app.wasm"))) throw error;
1699
- 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 });
1700
2061
  }
1701
2062
  return artifact;
1702
2063
  })().finally(() => builds.delete(hash));
@@ -1708,24 +2069,24 @@ var CONTENT_TYPES = {
1708
2069
  ".wasm": "application/wasm"
1709
2070
  };
1710
2071
  function kotlinArtifactFiles(hash) {
1711
- const dir = import_node_path5.default.join(buildsDir(), hash, "js");
1712
- return import_node_fs4.default.readdirSync(dir).sort().map((name) => {
1713
- 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)];
1714
2075
  if (!contentType) throw new Error(`unexpected kotlin artifact file ${name}`);
1715
- 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 };
1716
2077
  });
1717
2078
  }
1718
2079
  function serveKotlinArtifact(pathname, res) {
1719
2080
  if (!pathname.startsWith(KOTLIN_ARTIFACT_PREFIX)) return false;
1720
2081
  const [hash, file, ...rest] = pathname.slice(KOTLIN_ARTIFACT_PREFIX.length).split("/");
1721
- 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;
1722
2083
  if (!hash || !/^[0-9a-f]+$/.test(hash) || !file || rest.length > 0 || !type || file.includes("..")) {
1723
2084
  res.statusCode = 404;
1724
2085
  res.end("not a kotlin artifact");
1725
2086
  return true;
1726
2087
  }
1727
- const target = import_node_path5.default.join(buildsDir(), hash, "js", file);
1728
- 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)) {
1729
2090
  res.statusCode = 404;
1730
2091
  res.end(`kotlin artifact ${hash}/${file} was not built`);
1731
2092
  return true;
@@ -1733,7 +2094,7 @@ function serveKotlinArtifact(pathname, res) {
1733
2094
  res.setHeader("access-control-allow-origin", "*");
1734
2095
  res.setHeader("content-type", type);
1735
2096
  res.setHeader("cache-control", "public, max-age=31536000, immutable");
1736
- res.end(import_node_fs4.default.readFileSync(target));
2097
+ res.end(import_node_fs6.default.readFileSync(target));
1737
2098
  return true;
1738
2099
  }
1739
2100
  var KOTLIN_PACKAGE_PATH = "/__peach/kotlin-package";