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.
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/bundle-channel.cjs +2706 -2381
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +3227 -3220
- package/dist-lib/expo-swift-metadata.cjs +1 -1
- package/dist-lib/expo-swift-metadata.mjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +4538 -4213
- package/dist-lib/host/fetch-proxy-handler.cjs +6 -5
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +429 -279
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +645 -284
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +730 -580
- package/dist-lib/native-app-identity-project.cjs +2 -2
- package/dist-lib/native-app-identity-project.mjs +2 -2
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/pdfium-raster.cjs +1 -1
- package/dist-lib/pdfium-raster.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/public-origins-lib-esm.json +24 -24
- package/dist-lib/public-origins-lib.json +99 -59
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/reap-browser.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +5196 -4871
- package/dist-lib/swift-compile.cjs +2 -2
- package/dist-lib/swift-compile.mjs +2 -2
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +2 -2
- package/dist-lib/vite.cjs +6 -5
- package/dist-lib/worklet-executable.cjs +1 -1
- package/dist-lib/worklet-executable.mjs +1 -1
- package/kotlin/sdk.tar.gz +0 -0
- package/package.json +1 -1
- package/sdk/ios/System/Library/Frameworks/CFNetwork.framework/Headers/CFNetwork.h +10 -0
- package/src/android-autolinking.ts +45 -4
- package/src/android-bridge-packages.ts +2 -2
- package/src/android-gradle-sources.ts +143 -0
- package/src/androidAutolinkingContract.ts +8 -0
- package/src/androidGradleContract.ts +14 -0
- package/src/expo-kotlin-host.ts +3 -0
- package/src/java-module-abi.ts +145 -0
- package/src/javaAbiContract.ts +14 -0
- package/src/kotlin-host.ts +55 -3
- package/src/nitro-source.ts +2 -167
- package/src/react-native-autolinking.ts +153 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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;
|
|
@@ -12474,7 +12474,7 @@ var darwinRecordsRegion = (quoted) => quoted.length ? ["-Wl,--start-lib", ...quo
|
|
|
12474
12474
|
var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
|
|
12475
12475
|
var MULTI_MANIFEST_VERSION = 68;
|
|
12476
12476
|
var SWIFT_HEADER_PRODUCTS_TARGET = "PeachHeaderProducts";
|
|
12477
|
-
var compilerSourceDigest = true ? "
|
|
12477
|
+
var compilerSourceDigest = true ? "08a3436f8de8fff57c3ffe7822dc37ac9addd391678cb64d73212534a6e94aa1" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
|
|
12478
12478
|
function swiftArtifactHash(input, release, moduleRoot) {
|
|
12479
12479
|
const hash = (0, import_node_crypto13.createHash)("sha256");
|
|
12480
12480
|
hash.update(`swift-compile
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
1
|
+
/*! peach v0.1.2187 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/swift-compile.ts
|
|
4
4
|
import {
|
|
@@ -12454,7 +12454,7 @@ var darwinRecordsRegion = (quoted) => quoted.length ? ["-Wl,--start-lib", ...quo
|
|
|
12454
12454
|
var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
|
|
12455
12455
|
var MULTI_MANIFEST_VERSION = 68;
|
|
12456
12456
|
var SWIFT_HEADER_PRODUCTS_TARGET = "PeachHeaderProducts";
|
|
12457
|
-
var compilerSourceDigest = true ? "
|
|
12457
|
+
var compilerSourceDigest = true ? "08a3436f8de8fff57c3ffe7822dc37ac9addd391678cb64d73212534a6e94aa1" : swiftCompilerSourceDigest(import.meta.dirname);
|
|
12458
12458
|
function swiftArtifactHash(input, release, moduleRoot) {
|
|
12459
12459
|
const hash = createHash13("sha256");
|
|
12460
12460
|
hash.update(`swift-compile
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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;
|
package/dist-lib/swift.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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 __defProp = Object.defineProperty;
|
package/dist-lib/vite-swift.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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;
|
|
@@ -17269,7 +17269,7 @@ var darwinRecordsRegion = (quoted) => quoted.length ? ["-Wl,--start-lib", ...quo
|
|
|
17269
17269
|
var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
|
|
17270
17270
|
var MULTI_MANIFEST_VERSION = 68;
|
|
17271
17271
|
var SWIFT_HEADER_PRODUCTS_TARGET = "PeachHeaderProducts";
|
|
17272
|
-
var compilerSourceDigest = true ? "
|
|
17272
|
+
var compilerSourceDigest = true ? "08a3436f8de8fff57c3ffe7822dc37ac9addd391678cb64d73212534a6e94aa1" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
|
|
17273
17273
|
function swiftArtifactHash(input, release, moduleRoot) {
|
|
17274
17274
|
const hash = (0, import_node_crypto13.createHash)("sha256");
|
|
17275
17275
|
hash.update(`swift-compile
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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;
|
|
@@ -5391,7 +5391,7 @@ var FOUNDATION_IMPLICIT_MODULES = [
|
|
|
5391
5391
|
var FOUNDATION_IMPLICIT_FLAGS = FOUNDATION_IMPLICIT_MODULES.map(
|
|
5392
5392
|
(module2) => `, "-Xfrontend", "-import-module", "-Xfrontend", "${module2}"`
|
|
5393
5393
|
).join("");
|
|
5394
|
-
var compilerSourceDigest = true ? "
|
|
5394
|
+
var compilerSourceDigest = true ? "08a3436f8de8fff57c3ffe7822dc37ac9addd391678cb64d73212534a6e94aa1" : swiftCompilerSourceDigest2(__sootsim_import_meta_dirname);
|
|
5395
5395
|
var CORE_FOUNDATION_HANDLE_IMPORTS = [
|
|
5396
5396
|
"CFAllocator",
|
|
5397
5397
|
"CFArray",
|
|
@@ -5444,8 +5444,6 @@ init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
|
|
|
5444
5444
|
|
|
5445
5445
|
// src/nitro-source.ts
|
|
5446
5446
|
init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
|
|
5447
|
-
var import_node_child_process7 = require("node:child_process");
|
|
5448
|
-
var import_node_util6 = require("node:util");
|
|
5449
5447
|
|
|
5450
5448
|
// src/nitro-dependencies.ts
|
|
5451
5449
|
init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
|
|
@@ -5592,7 +5590,10 @@ var RN_FMT_12_DEPENDENCIES = [
|
|
|
5592
5590
|
}
|
|
5593
5591
|
];
|
|
5594
5592
|
|
|
5595
|
-
// src/
|
|
5593
|
+
// src/react-native-autolinking.ts
|
|
5594
|
+
init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
|
|
5595
|
+
var import_node_child_process7 = require("node:child_process");
|
|
5596
|
+
var import_node_util6 = require("node:util");
|
|
5596
5597
|
var run5 = (0, import_node_util6.promisify)(import_node_child_process7.execFile);
|
|
5597
5598
|
|
|
5598
5599
|
// src/workspace-root.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! peach v0.1.
|
|
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 __defProp = Object.defineProperty;
|
package/kotlin/sdk.tar.gz
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -26,4 +26,14 @@ CFN_EXPORT const CFStringRef kCFStreamPropertySSLPeerCertificates CF_DEPRECATED(
|
|
|
26
26
|
CFN_EXPORT const CFStringRef kCFStreamSSLAllowsExpiredCertificates CF_DEPRECATED(10_4, 10_6, 2_0, 4_0);
|
|
27
27
|
CFN_EXPORT const CFStringRef kCFStreamSSLAllowsExpiredRoots CF_DEPRECATED(10_4, 10_6, 2_0, 4_0);
|
|
28
28
|
CFN_EXPORT const CFStringRef kCFStreamSSLAllowsAnyRoot CF_DEPRECATED(10_4, 10_6, 2_0, 4_0);
|
|
29
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertySSLContext CF_AVAILABLE(10_9, 5_0);
|
|
30
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertyNoCellular CF_AVAILABLE(10_8, 5_0);
|
|
31
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertyConnectionIsCellular CF_AVAILABLE(10_8, 6_0);
|
|
32
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertyAllowExpensiveNetworkAccess API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));
|
|
33
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertyConnectionIsExpensive API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));
|
|
34
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertyAllowConstrainedNetworkAccess API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));
|
|
35
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertyProxyLocalBypass CF_AVAILABLE(10_4, 2_0);
|
|
36
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertySocketRemoteHost CF_AVAILABLE(10_3, 2_0);
|
|
37
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertySocketRemoteNetService CF_AVAILABLE(10_3, 2_0);
|
|
38
|
+
CFN_EXPORT const CFStringRef kCFStreamPropertySocketExtendedBackgroundIdleMode CF_AVAILABLE(10_11, 9_0);
|
|
29
39
|
CF_EXTERN_C_END
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
// use
|
|
2
|
-
// plugin-only Android packages follow the same autolinking as Gradle.
|
|
1
|
+
// use each native autolinker for its module families and platform exclusions.
|
|
3
2
|
import { execFile } from 'node:child_process'
|
|
4
3
|
import fs from 'node:fs'
|
|
5
4
|
import { createRequire } from 'node:module'
|
|
@@ -8,6 +7,8 @@ import { promisify } from 'node:util'
|
|
|
8
7
|
import { readAndroidAutolinkedPackages } from './androidAutolinkingContract'
|
|
9
8
|
import { PEACH_FORKED_SCRIPT_ENV } from './forked-script-contract'
|
|
10
9
|
import { isRecord } from './is-record'
|
|
10
|
+
import { reactNativeAutolinkingConfig } from './react-native-autolinking'
|
|
11
|
+
import type { AndroidAutolinkedDependency } from './androidAutolinkingContract'
|
|
11
12
|
|
|
12
13
|
const run = promisify(execFile)
|
|
13
14
|
|
|
@@ -71,6 +72,46 @@ async function resolveAndroidModules(
|
|
|
71
72
|
export async function collectAndroidAutolinkedPackages(
|
|
72
73
|
appRoot: string,
|
|
73
74
|
): Promise<string[]> {
|
|
74
|
-
const modules = await
|
|
75
|
-
|
|
75
|
+
const [modules, dependencies] = await Promise.all([
|
|
76
|
+
resolveExpoAndroidAutolinking(appRoot),
|
|
77
|
+
resolveReactNativeAndroidAutolinking(appRoot),
|
|
78
|
+
])
|
|
79
|
+
return readAndroidAutolinkedPackages([
|
|
80
|
+
...modules.map((entry) => entry.packageName),
|
|
81
|
+
...dependencies.map((entry) => entry.name),
|
|
82
|
+
])
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function resolveReactNativeAndroidAutolinking(
|
|
86
|
+
appRoot: string,
|
|
87
|
+
): Promise<AndroidAutolinkedDependency[]> {
|
|
88
|
+
const config = await reactNativeAutolinkingConfig(appRoot, 'android')
|
|
89
|
+
if (!isRecord(config) || !isRecord(config.dependencies))
|
|
90
|
+
throw new Error(`${appRoot}: React Native autolinking config has no dependencies`)
|
|
91
|
+
const linked: AndroidAutolinkedDependency[] = []
|
|
92
|
+
for (const [name, dependency] of Object.entries(config.dependencies)) {
|
|
93
|
+
if (!isRecord(dependency) || !isRecord(dependency.platforms))
|
|
94
|
+
throw new Error(
|
|
95
|
+
`${appRoot}: React Native autolinking dependency ${name} is malformed`,
|
|
96
|
+
)
|
|
97
|
+
const android = dependency.platforms.android
|
|
98
|
+
if (android == null) continue
|
|
99
|
+
if (!isRecord(android) || typeof dependency.root !== 'string')
|
|
100
|
+
throw new Error(
|
|
101
|
+
`${appRoot}: React Native autolinking dependency ${name} has no Android project`,
|
|
102
|
+
)
|
|
103
|
+
const string = (field: string): string | null => {
|
|
104
|
+
const value = android[field]
|
|
105
|
+
if (value == null || typeof value === 'string') return value ?? null
|
|
106
|
+
throw new Error(`${appRoot}: Android dependency ${name} has invalid ${field}`)
|
|
107
|
+
}
|
|
108
|
+
linked.push({
|
|
109
|
+
name,
|
|
110
|
+
root: dependency.root,
|
|
111
|
+
sourceDir: string('sourceDir'),
|
|
112
|
+
packageImportPath: string('packageImportPath'),
|
|
113
|
+
packageInstance: string('packageInstance'),
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
return linked
|
|
76
117
|
}
|
|
@@ -50,7 +50,7 @@ export interface BridgeSelection {
|
|
|
50
50
|
const qualified = (file: { package: string }, name: string) =>
|
|
51
51
|
file.package ? `${file.package}.${name}` : name
|
|
52
52
|
|
|
53
|
-
function
|
|
53
|
+
export function readBridgeMethod(value: unknown): BridgeMethod {
|
|
54
54
|
if (
|
|
55
55
|
!isRecord(value) ||
|
|
56
56
|
typeof value.name !== 'string' ||
|
|
@@ -117,7 +117,7 @@ export function readBridgeFiles(output: string): BridgeFile[] {
|
|
|
117
117
|
!Array.isArray(entry.methods)
|
|
118
118
|
)
|
|
119
119
|
throw new Error('bridge-modules printed an invalid module')
|
|
120
|
-
return { name: entry.name, methods: entry.methods.map(
|
|
120
|
+
return { name: entry.name, methods: entry.methods.map(readBridgeMethod) }
|
|
121
121
|
}),
|
|
122
122
|
}
|
|
123
123
|
})
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process'
|
|
2
|
+
import { randomBytes } from 'node:crypto'
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { promisify } from 'node:util'
|
|
6
|
+
import { PEACH_FORKED_SCRIPT_ENV } from './forked-script-contract'
|
|
7
|
+
import { isRecord } from './is-record'
|
|
8
|
+
import { kotlinHome } from './kotlin-toolchain'
|
|
9
|
+
import type {
|
|
10
|
+
AndroidGradleSourceRequest,
|
|
11
|
+
AndroidGradleSources,
|
|
12
|
+
} from './androidGradleContract'
|
|
13
|
+
|
|
14
|
+
const run = promisify(execFile)
|
|
15
|
+
const modelQuery = `
|
|
16
|
+
import groovy.json.JsonOutput
|
|
17
|
+
import groovy.json.JsonSlurper
|
|
18
|
+
|
|
19
|
+
def request = new JsonSlurper().parseText(new String(Base64.decoder.decode('__PEACH_REQUEST__'), 'UTF-8'))
|
|
20
|
+
gradle.projectsEvaluated {
|
|
21
|
+
if (gradle.rootProject.projectDir.canonicalPath != request.root) return
|
|
22
|
+
def selected = []
|
|
23
|
+
request.projects.eachWithIndex { directory, index ->
|
|
24
|
+
def matches = gradle.rootProject.allprojects.findAll { it.projectDir.canonicalPath == directory }
|
|
25
|
+
if (matches.size() != 1) throw new GradleException('Expected one Android project for ' + directory)
|
|
26
|
+
def project = matches[0]
|
|
27
|
+
if (project.pluginManager.hasPlugin('org.jetbrains.kotlin.multiplatform')) {
|
|
28
|
+
throw new GradleException('Kotlin multiplatform source selection is not supported: ' + project.path)
|
|
29
|
+
}
|
|
30
|
+
def library = project.pluginManager.hasPlugin('com.android.library')
|
|
31
|
+
if (!library && !project.pluginManager.hasPlugin('com.android.application')) {
|
|
32
|
+
throw new GradleException('Project has no Android application or library plugin: ' + project.path)
|
|
33
|
+
}
|
|
34
|
+
def android = project.extensions.getByName('android')
|
|
35
|
+
def variants = library ? android.libraryVariants : android.applicationVariants
|
|
36
|
+
def variant = variants.find { it.name == request.variant }
|
|
37
|
+
if (variant == null) throw new GradleException('Android variant ' + request.variant + ' is absent: ' + project.path)
|
|
38
|
+
def generators = []
|
|
39
|
+
def buildConfig = variant.generateBuildConfigProvider
|
|
40
|
+
if (buildConfig != null) generators.add(buildConfig)
|
|
41
|
+
if (project.pluginManager.hasPlugin('com.facebook.react')) {
|
|
42
|
+
generators.add(project.tasks.named('generateCodegenArtifactsFromSchema'))
|
|
43
|
+
}
|
|
44
|
+
def kotlin = project.tasks.findByName('compile' + variant.name.capitalize() + 'Kotlin')
|
|
45
|
+
def kotlinSources = kotlin == null ? project.files() : kotlin.sources
|
|
46
|
+
def javaSources = variant.javaCompileProvider.get().source
|
|
47
|
+
def query = project.tasks.register(request.task) {
|
|
48
|
+
dependsOn(generators)
|
|
49
|
+
dependsOn(kotlinSources.buildDependencies, javaSources.buildDependencies)
|
|
50
|
+
doLast {
|
|
51
|
+
def files = (kotlinSources.files + javaSources.files).unique()
|
|
52
|
+
def unknown = files.find { !it.name.endsWith('.kt') && !it.name.endsWith('.java') }
|
|
53
|
+
if (unknown != null) throw new GradleException('Unsupported Android source: ' + unknown)
|
|
54
|
+
new File(request.output, index.toString() + '.json').text = JsonOutput.toJson([
|
|
55
|
+
projectDir:project.projectDir.canonicalPath,
|
|
56
|
+
projectPath:project.path,
|
|
57
|
+
variant:variant.name,
|
|
58
|
+
applicationId:library ? null : variant.applicationId,
|
|
59
|
+
kotlin:files.findAll { it.name.endsWith('.kt') }.collect { it.absolutePath }.sort(),
|
|
60
|
+
java:files.findAll { it.name.endsWith('.java') }.collect { it.absolutePath }.sort()
|
|
61
|
+
])
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
selected.add(query)
|
|
65
|
+
}
|
|
66
|
+
gradle.rootProject.tasks.register(request.task + 'All') { dependsOn(selected) }
|
|
67
|
+
}
|
|
68
|
+
`
|
|
69
|
+
|
|
70
|
+
export async function resolveAndroidGradleSources(
|
|
71
|
+
request: AndroidGradleSourceRequest,
|
|
72
|
+
): Promise<AndroidGradleSources[]> {
|
|
73
|
+
let { root } = request
|
|
74
|
+
const { projects: projectDirs, variant } = request
|
|
75
|
+
if (projectDirs.length === 0) return []
|
|
76
|
+
if (!path.isAbsolute(root) || projectDirs.some((dir) => !path.isAbsolute(dir)))
|
|
77
|
+
throw new Error('Android Gradle source selection requires absolute project paths')
|
|
78
|
+
if (!variant) throw new Error('Android Gradle source selection requires a variant')
|
|
79
|
+
root = fs.realpathSync(root)
|
|
80
|
+
const projects = [...new Set(projectDirs.map((dir) => fs.realpathSync(dir)))]
|
|
81
|
+
const parent = path.join(kotlinHome(), 'gradle-sources')
|
|
82
|
+
fs.mkdirSync(parent, { recursive: true })
|
|
83
|
+
const work = fs.mkdtempSync(path.join(parent, '.query-'))
|
|
84
|
+
const task = `peachAndroidSources${randomBytes(8).toString('hex')}`
|
|
85
|
+
const script = path.join(work, 'sources.gradle')
|
|
86
|
+
const encoded = Buffer.from(
|
|
87
|
+
JSON.stringify({ root, projects, variant, output: work, task }),
|
|
88
|
+
).toString('base64')
|
|
89
|
+
fs.writeFileSync(script, modelQuery.replace('__PEACH_REQUEST__', encoded))
|
|
90
|
+
try {
|
|
91
|
+
await run(
|
|
92
|
+
'bash',
|
|
93
|
+
[
|
|
94
|
+
path.join(root, 'gradlew'),
|
|
95
|
+
'--init-script',
|
|
96
|
+
script,
|
|
97
|
+
`${task}All`,
|
|
98
|
+
'--no-daemon',
|
|
99
|
+
'--no-configuration-cache',
|
|
100
|
+
'--max-workers=1',
|
|
101
|
+
'--console=plain',
|
|
102
|
+
],
|
|
103
|
+
{
|
|
104
|
+
cwd: root,
|
|
105
|
+
timeout: 300_000,
|
|
106
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
107
|
+
env: { ...process.env, [PEACH_FORKED_SCRIPT_ENV]: '1' },
|
|
108
|
+
},
|
|
109
|
+
)
|
|
110
|
+
return projects.map((projectDir, index): AndroidGradleSources => {
|
|
111
|
+
const value: unknown = JSON.parse(
|
|
112
|
+
fs.readFileSync(path.join(work, `${index}.json`), 'utf8'),
|
|
113
|
+
)
|
|
114
|
+
if (
|
|
115
|
+
!isRecord(value) ||
|
|
116
|
+
value.projectDir !== projectDir ||
|
|
117
|
+
value.variant !== variant ||
|
|
118
|
+
typeof value.projectPath !== 'string' ||
|
|
119
|
+
(value.applicationId !== null && typeof value.applicationId !== 'string')
|
|
120
|
+
)
|
|
121
|
+
throw new Error('Gradle printed an invalid Android project source model')
|
|
122
|
+
const sources = (field: 'kotlin' | 'java'): string[] => {
|
|
123
|
+
const list = value[field]
|
|
124
|
+
if (
|
|
125
|
+
!Array.isArray(list) ||
|
|
126
|
+
!list.every((file) => typeof file === 'string' && path.isAbsolute(file))
|
|
127
|
+
)
|
|
128
|
+
throw new Error(`Gradle printed invalid Android ${field} source paths`)
|
|
129
|
+
return list.map(String)
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
projectDir,
|
|
133
|
+
projectPath: value.projectPath,
|
|
134
|
+
variant,
|
|
135
|
+
applicationId: value.applicationId,
|
|
136
|
+
kotlin: sources('kotlin'),
|
|
137
|
+
java: sources('java'),
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
} finally {
|
|
141
|
+
fs.rmSync(work, { recursive: true, force: true })
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -6,6 +6,14 @@ import {
|
|
|
6
6
|
|
|
7
7
|
const FOOTER = '__peachAndroidAutolinkedPackages'
|
|
8
8
|
|
|
9
|
+
export interface AndroidAutolinkedDependency {
|
|
10
|
+
name: string
|
|
11
|
+
root: string
|
|
12
|
+
sourceDir: string | null
|
|
13
|
+
packageImportPath: string | null
|
|
14
|
+
packageInstance: string | null
|
|
15
|
+
}
|
|
16
|
+
|
|
9
17
|
export function readAndroidAutolinkedPackages(value: unknown): string[] {
|
|
10
18
|
if (
|
|
11
19
|
!Array.isArray(value) ||
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface AndroidGradleSourceRequest {
|
|
2
|
+
root: string
|
|
3
|
+
projects: readonly string[]
|
|
4
|
+
variant: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface AndroidGradleSources {
|
|
8
|
+
projectDir: string
|
|
9
|
+
projectPath: string
|
|
10
|
+
variant: string
|
|
11
|
+
applicationId: string | null
|
|
12
|
+
kotlin: string[]
|
|
13
|
+
java: string[]
|
|
14
|
+
}
|
package/src/expo-kotlin-host.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { peachAnsweredNativePackages } from './answeredNativePackages'
|
|
|
15
15
|
import { isLoopbackHost } from './backend-origin'
|
|
16
16
|
import { isRecord } from './is-record'
|
|
17
17
|
import { peachKotlinModuleRoot } from './kotlin-module'
|
|
18
|
+
import type { AndroidGradleSourceRequest } from './androidGradleContract'
|
|
18
19
|
import type { ExpoKotlinCompilationResult } from './expoKotlinContract'
|
|
19
20
|
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
20
21
|
|
|
@@ -24,6 +25,8 @@ export interface ExpoKotlinModules {
|
|
|
24
25
|
// the registration names Android's ExpoModulesPackageList passes, in order
|
|
25
26
|
modules: { classifier: string; name: string | null }[]
|
|
26
27
|
sources: string[]
|
|
28
|
+
javaSpecs?: string[]
|
|
29
|
+
gradleSources?: AndroidGradleSourceRequest
|
|
27
30
|
// the app's own legacy React Native modules, hosted beside the Expo ones
|
|
28
31
|
bridge: BridgeSelection | null
|
|
29
32
|
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process'
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { promisify } from 'node:util'
|
|
6
|
+
import { readBridgeMethod } from './android-bridge-packages'
|
|
7
|
+
import { isRecord } from './is-record'
|
|
8
|
+
import { kotlinHome } from './kotlin-toolchain'
|
|
9
|
+
import type { JavaModuleSpec, JavaModuleSpecs } from './javaAbiContract'
|
|
10
|
+
import type { KotlinToolchainInstallation } from './kotlinSdkContract'
|
|
11
|
+
|
|
12
|
+
const run = promisify(execFile)
|
|
13
|
+
export const JAVA_BINDINGS_INITIALIZER = 'initializeJavaBindings'
|
|
14
|
+
|
|
15
|
+
export async function readJavaModuleSpecs(
|
|
16
|
+
files: string[],
|
|
17
|
+
sdkRoot: string,
|
|
18
|
+
toolchain: KotlinToolchainInstallation,
|
|
19
|
+
): Promise<JavaModuleSpecs> {
|
|
20
|
+
const digest = createHash('sha256')
|
|
21
|
+
const parent = path.join(kotlinHome(), 'java-specs')
|
|
22
|
+
fs.mkdirSync(parent, { recursive: true })
|
|
23
|
+
const work = fs.mkdtempSync(path.join(parent, '.read-'))
|
|
24
|
+
try {
|
|
25
|
+
const origins = new Map<string, string>()
|
|
26
|
+
for (const [index, file] of files.entries()) {
|
|
27
|
+
const bytes = fs.readFileSync(file)
|
|
28
|
+
digest.update(file).update('\0').update(bytes).update('\0')
|
|
29
|
+
const target = path.join(work, String(index), path.basename(file))
|
|
30
|
+
fs.mkdirSync(path.dirname(target))
|
|
31
|
+
fs.writeFileSync(target, bytes)
|
|
32
|
+
origins.set(target, file)
|
|
33
|
+
}
|
|
34
|
+
const { stdout } = await run(
|
|
35
|
+
path.join(toolchain.javaHome, 'bin', 'java'),
|
|
36
|
+
[
|
|
37
|
+
'-cp',
|
|
38
|
+
[
|
|
39
|
+
path.join(sdkRoot, 'tools.jar'),
|
|
40
|
+
path.resolve(path.dirname(toolchain.kotlinc), '../lib/kotlin-compiler.jar'),
|
|
41
|
+
path.resolve(path.dirname(toolchain.kotlinc), '../lib/kotlin-stdlib.jar'),
|
|
42
|
+
].join(path.delimiter),
|
|
43
|
+
'dev.peach.tools.javaabi.JavaModuleSpecsKt',
|
|
44
|
+
...origins.keys(),
|
|
45
|
+
],
|
|
46
|
+
{ maxBuffer: 16 * 1024 * 1024 },
|
|
47
|
+
)
|
|
48
|
+
const specs = stdout
|
|
49
|
+
.split('\n')
|
|
50
|
+
.filter(Boolean)
|
|
51
|
+
.map((line): JavaModuleSpec => {
|
|
52
|
+
const row: unknown = JSON.parse(line)
|
|
53
|
+
if (
|
|
54
|
+
!isRecord(row) ||
|
|
55
|
+
typeof row.file !== 'string' ||
|
|
56
|
+
typeof row.className !== 'string' ||
|
|
57
|
+
(row.name !== null && typeof row.name !== 'string') ||
|
|
58
|
+
typeof row.source !== 'string' ||
|
|
59
|
+
!Array.isArray(row.methods)
|
|
60
|
+
)
|
|
61
|
+
throw new Error('Java module reader printed an invalid spec')
|
|
62
|
+
const file = origins.get(row.file)
|
|
63
|
+
if (!file) throw new Error('Java module reader named an unknown input')
|
|
64
|
+
return {
|
|
65
|
+
file,
|
|
66
|
+
className: row.className,
|
|
67
|
+
name: row.name,
|
|
68
|
+
source: row.source,
|
|
69
|
+
methods: row.methods.map(readBridgeMethod),
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
return { sha256: digest.digest('hex'), specs }
|
|
73
|
+
} finally {
|
|
74
|
+
fs.rmSync(work, { recursive: true, force: true })
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function compileJavaModuleAbi(input: {
|
|
79
|
+
specs: JavaModuleSpecs
|
|
80
|
+
work: string
|
|
81
|
+
hash: string
|
|
82
|
+
toolchain: KotlinToolchainInstallation
|
|
83
|
+
libraries: string[]
|
|
84
|
+
sdkRoot: string
|
|
85
|
+
sdkLibrary: string
|
|
86
|
+
language: string
|
|
87
|
+
}): Promise<string> {
|
|
88
|
+
const { specs, work, hash, toolchain, libraries, sdkRoot, sdkLibrary, language } = input
|
|
89
|
+
const directory = path.join(work, 'java-abi')
|
|
90
|
+
fs.mkdirSync(directory)
|
|
91
|
+
const sources = specs.specs.map((spec, index) => {
|
|
92
|
+
const target = path.join(directory, `Spec${index}.kt`)
|
|
93
|
+
fs.writeFileSync(target, spec.source)
|
|
94
|
+
return target
|
|
95
|
+
})
|
|
96
|
+
const initializer = path.join(directory, 'Bindings.kt')
|
|
97
|
+
fs.writeFileSync(
|
|
98
|
+
initializer,
|
|
99
|
+
[
|
|
100
|
+
'package dev.peach.jni',
|
|
101
|
+
`internal fun ${JAVA_BINDINGS_INITIALIZER}() { error("Java bindings require the compiler plugin") }`,
|
|
102
|
+
].join('\n'),
|
|
103
|
+
)
|
|
104
|
+
const name = `peach-java-abi-${hash}`
|
|
105
|
+
await run(
|
|
106
|
+
toolchain.kotlinc,
|
|
107
|
+
[
|
|
108
|
+
'-J-Xmx2g',
|
|
109
|
+
'-Xwasm-target=js',
|
|
110
|
+
'-libraries',
|
|
111
|
+
libraries.join(path.delimiter),
|
|
112
|
+
`-Xplugin=${path.join(sdkRoot, 'plugin.jar')}`,
|
|
113
|
+
`-Xfriend-modules=${sdkLibrary}`,
|
|
114
|
+
'-language-version',
|
|
115
|
+
language,
|
|
116
|
+
'-api-version',
|
|
117
|
+
language,
|
|
118
|
+
'-nowarn',
|
|
119
|
+
'-ir-output-dir',
|
|
120
|
+
directory,
|
|
121
|
+
'-ir-output-name',
|
|
122
|
+
name,
|
|
123
|
+
...sources,
|
|
124
|
+
initializer,
|
|
125
|
+
],
|
|
126
|
+
{ maxBuffer: 16 * 1024 * 1024 },
|
|
127
|
+
)
|
|
128
|
+
const library = path.join(directory, 'java-abi.klib')
|
|
129
|
+
await run(
|
|
130
|
+
path.join(toolchain.javaHome, 'bin', 'java'),
|
|
131
|
+
[
|
|
132
|
+
'-cp',
|
|
133
|
+
[
|
|
134
|
+
path.join(sdkRoot, 'tools.jar'),
|
|
135
|
+
path.resolve(path.dirname(toolchain.kotlinc), '../lib/kotlin-compiler.jar'),
|
|
136
|
+
path.resolve(path.dirname(toolchain.kotlinc), '../lib/kotlin-stdlib.jar'),
|
|
137
|
+
].join(path.delimiter),
|
|
138
|
+
'dev.peach.tools.platform.JavaPlatformTypesKt',
|
|
139
|
+
path.join(directory, `${name}.klib`),
|
|
140
|
+
library,
|
|
141
|
+
],
|
|
142
|
+
{ maxBuffer: 16 * 1024 * 1024 },
|
|
143
|
+
)
|
|
144
|
+
return library
|
|
145
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BridgeMethod } from './android-bridge-packages'
|
|
2
|
+
|
|
3
|
+
export interface JavaModuleSpec {
|
|
4
|
+
file: string
|
|
5
|
+
className: string
|
|
6
|
+
name: string | null
|
|
7
|
+
source: string
|
|
8
|
+
methods: BridgeMethod[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface JavaModuleSpecs {
|
|
12
|
+
sha256: string
|
|
13
|
+
specs: JavaModuleSpec[]
|
|
14
|
+
}
|