peachsim 0.1.527 → 0.1.571
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/README.md +28 -28
- package/cli/app-fonts.ts +1 -1
- package/cli/app-splash.ts +1 -1
- package/cli/bin.ts +1 -1
- package/cli/bridge-diagnostics.ts +1 -1
- package/cli/bridge-flow-runner.ts +72 -12
- package/cli/cloud-client.ts +273 -6
- package/cli/cloud-dispatch.ts +23 -2
- package/cli/cloud-session.ts +60 -4
- package/cli/cloud-test-result-files.ts +97 -0
- package/cli/cloud-test-tunnel.ts +354 -0
- package/cli/commands/box/bundle-plane.ts +2 -2
- package/cli/commands/box/checkout-plane.ts +1 -1
- package/cli/commands/box/rnx-command.ts +2 -2
- package/cli/commands/box/search-command.ts +2 -2
- package/cli/commands/box.ts +8 -8
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/control.ts +22 -3
- package/cli/commands/detox.ts +1 -1
- package/cli/commands/device.ts +1 -1
- package/cli/commands/diagnose.ts +1 -1
- package/cli/commands/film.ts +1 -1
- package/cli/commands/flow.ts +60 -3
- package/cli/commands/inspect/actions.ts +1 -1
- package/cli/commands/inspect/core.ts +6 -7
- package/cli/commands/inspect/find.ts +2 -1
- package/cli/commands/inspect/resolve-target.ts +5 -3
- package/cli/commands/inspect/shared.ts +1 -1
- package/cli/commands/inspect/wait-event.ts +1 -1
- package/cli/commands/inspect/wait-selector.ts +15 -4
- package/cli/commands/inspect.ts +19 -14
- package/cli/commands/maestro.ts +582 -69
- package/cli/commands/permissions.ts +1 -1
- package/cli/commands/platform.ts +205 -8
- package/cli/commands/preview.ts +2 -2
- package/cli/commands/record.ts +2 -2
- package/cli/commands/report-issue.ts +2 -2
- package/cli/commands/screenshot-layers.ts +1 -1
- package/cli/commands/screenshot.ts +1 -1
- package/cli/commands/setup.ts +2 -2
- package/cli/commands/test.ts +600 -117
- package/cli/commands/three-mode.ts +1 -1
- package/cli/commands/upload.ts +5 -5
- package/cli/commands/what-happened.ts +1 -1
- package/cli/desktop-companion.ts +3 -3
- package/cli/drivers/playwright-sim-host.ts +2 -2
- package/cli/flow-file.ts +7 -0
- package/cli/flow-live-status.ts +65 -8
- package/cli/help-core.ts +3 -3
- package/cli/hidden-runtime-alias.ts +1 -1
- package/cli/maestro-report.ts +180 -0
- package/cli/main.ts +1 -1
- package/cli/outbound-endpoints.ts +187 -136
- package/cli/parse-args.ts +1 -1
- package/cli/registry.ts +1 -1
- package/cli/resolve-assets.ts +1 -1
- package/cli/run-registry.ts +10 -1
- package/cli/send-to-box.ts +4 -4
- package/cli/ws-bridge.ts +3 -5
- package/detox/expectations.ts +1 -1
- package/detox/gestures.ts +2 -2
- package/detox/index.ts +71 -29
- package/detox/jest-preset.cjs +5 -5
- package/detox/jest-setup-after-env.cjs +1 -1
- package/dist-lib/agent-daemon-client.cjs +2 -2
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +2 -2
- package/dist-lib/attached-projects.cjs +2 -2
- 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/capture-contract.cjs +94 -3
- package/dist-lib/capture-contract.mjs +93 -3
- package/dist-lib/cli-constants.cjs +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 +116 -0
- package/dist-lib/cloud-test-args.mjs +86 -0
- package/dist-lib/cloud.cjs +2 -2
- package/dist-lib/cloud.mjs +2 -2
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +106 -25
- package/dist-lib/detox/jest-preset.cjs +5 -5
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +150 -65
- package/dist-lib/host/fetch-proxy-handler.cjs +28 -2
- package/dist-lib/host/fetch-proxy-overrides.cjs +33 -3
- package/dist-lib/host/fetch-proxy-overrides.mjs +30 -2
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +224 -41
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +2 -2
- package/dist-lib/menu.mjs +2 -2
- 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 +3 -3
- package/dist-lib/metro-production-bundle.mjs +3 -3
- package/dist-lib/metro.cjs +8 -8
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +2 -2
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +31 -15
- package/dist-lib/sdk.cjs +3 -2
- package/dist-lib/sdk.mjs +3 -2
- package/dist-lib/skills.cjs +478 -266
- package/dist-lib/swift-compile.cjs +372 -0
- package/dist-lib/swift-compile.mjs +339 -0
- package/dist-lib/swift-package.cjs +78 -0
- package/dist-lib/swift-package.mjs +52 -0
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +583 -16
- package/dist-lib/vite.cjs +483 -150
- package/package.json +30 -9
- package/scripts/dev-server-scanner.ts +41 -14
- package/scripts/optional-demo-registry.ts +3 -3
- package/skills/contrast/SKILL.md +9 -9
- package/skills/rnx-debug/SKILL.md +14 -4
- package/skills/rnx-perf/SKILL.md +5 -5
- package/skills/rnx-setup/SKILL.md +11 -11
- package/skills/rnx-test/SKILL.md +14 -14
- package/skills/rnx-visual/SKILL.md +6 -6
- package/src/agent-sessions.ts +3 -3
- package/src/attached-projects.ts +1 -1
- package/src/bridge-contract-input.ts +1 -1
- package/src/bridge-contract.ts +23 -5
- package/src/capture-contract.ts +145 -3
- package/src/cloud-test-args.ts +100 -0
- package/src/config.ts +2 -2
- package/src/connect.ts +2 -2
- package/src/home-paths.ts +3 -3
- package/src/host/bridge-host.ts +2 -2
- package/src/host/fetch-proxy-handler.ts +4 -3
- package/src/host/fetch-proxy-overrides.ts +41 -0
- package/src/host/plane-host.ts +2 -2
- package/src/index.ts +3 -0
- package/src/metro-plugin.ts +4 -4
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-seam-manifest.ts +6 -6
- package/src/public-brand.ts +1 -1
- package/src/rolldown-plugin-swift.ts +16 -12
- package/src/runtime-assets.ts +8 -6
- package/src/screenshots/frame-compose.ts +24 -56
- package/src/screenshots/org-deck.ts +1 -1
- package/src/screenshots/registry.ts +4 -4
- package/src/screenshots/schema.ts +1 -1
- package/src/sdk.ts +2 -2
- package/src/settings-bundle.ts +1 -1
- package/src/sim-client.ts +2 -4
- package/src/skills/builtin/compat-check.ts +1 -1
- package/src/swift-compile.ts +359 -0
- package/src/swift-package.ts +69 -0
- package/src/swift-submit.ts +3 -2
- package/src/vite-plugin-one.ts +1 -1
- package/src/vite-plugin-swift.ts +114 -113
- package/src/vite-plugin.ts +30 -17
- package/src/worklets-babel.ts +2 -2
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.571 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -40,7 +40,7 @@ __export(vite_plugin_one_exports, {
|
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(vite_plugin_one_exports);
|
|
42
42
|
var import_fs2 = __toESM(require("fs"), 1);
|
|
43
|
-
var
|
|
43
|
+
var import_node_crypto4 = require("node:crypto");
|
|
44
44
|
var import_path2 = __toESM(require("path"), 1);
|
|
45
45
|
|
|
46
46
|
// src/bridge-constants.ts
|
|
@@ -622,7 +622,7 @@ function findMonorepoRoot() {
|
|
|
622
622
|
if (_monorepoRootCache !== void 0) return _monorepoRootCache;
|
|
623
623
|
let dir = import_path.default.dirname((0, import_url.fileURLToPath)(__sootsim_import_meta_url));
|
|
624
624
|
for (let i = 0; i < 12 && dir !== import_path.default.dirname(dir); i++) {
|
|
625
|
-
if (import_fs.default.existsSync(import_path.default.join(dir, "packages/
|
|
625
|
+
if (import_fs.default.existsSync(import_path.default.join(dir, "packages/peach-engine/package.json")) && import_fs.default.existsSync(import_path.default.join(dir, "public/sootsim"))) {
|
|
626
626
|
_monorepoRootCache = dir;
|
|
627
627
|
return dir;
|
|
628
628
|
}
|
|
@@ -636,7 +636,7 @@ function resolveDevCheckoutRuntimeRoot() {
|
|
|
636
636
|
const root = findMonorepoRoot();
|
|
637
637
|
if (!root) return null;
|
|
638
638
|
const devBuild = import_path.default.join(root, "public/sootsim");
|
|
639
|
-
if (import_fs.default.existsSync(import_path.default.join(devBuild, "index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine/index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine-tenant/worker.js"))) {
|
|
639
|
+
if (import_fs.default.existsSync(import_path.default.join(devBuild, "index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine/index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine-tenant/worker.js")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine-tenant/worker.prod.js"))) {
|
|
640
640
|
return devBuild;
|
|
641
641
|
}
|
|
642
642
|
return null;
|
|
@@ -713,10 +713,10 @@ function resolveRuntimeRootForHostname(hostname) {
|
|
|
713
713
|
const version = runtimeVersionFromHostname(hostname);
|
|
714
714
|
return version ? resolveInstalledRuntimeRoot(version) : null;
|
|
715
715
|
}
|
|
716
|
-
function resolveRuntimeRootForRequestHost(
|
|
717
|
-
if (!
|
|
716
|
+
function resolveRuntimeRootForRequestHost(host2) {
|
|
717
|
+
if (!host2) return resolveActiveRuntimeRoot();
|
|
718
718
|
try {
|
|
719
|
-
return resolveRuntimeRootForHostname(new URL(`http://${
|
|
719
|
+
return resolveRuntimeRootForHostname(new URL(`http://${host2}`).hostname);
|
|
720
720
|
} catch {
|
|
721
721
|
return null;
|
|
722
722
|
}
|
|
@@ -757,12 +757,10 @@ function serveRuntimeFile(req, res, fullPath) {
|
|
|
757
757
|
}
|
|
758
758
|
|
|
759
759
|
// src/vite-plugin-swift.ts
|
|
760
|
-
var
|
|
761
|
-
var
|
|
762
|
-
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
760
|
+
var import_node_crypto3 = require("node:crypto");
|
|
761
|
+
var import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
763
762
|
var import_node_os2 = __toESM(require("node:os"), 1);
|
|
764
|
-
var
|
|
765
|
-
var import_node_util = require("node:util");
|
|
763
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
766
764
|
|
|
767
765
|
// ../sootsim-swift/src/bundleAssets.ts
|
|
768
766
|
var RASTER_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
@@ -797,13 +795,13 @@ function imagesetName(contentsPath) {
|
|
|
797
795
|
if (!leaf.endsWith(".imageset")) return null;
|
|
798
796
|
return leaf.slice(0, -".imageset".length) || null;
|
|
799
797
|
}
|
|
800
|
-
function isFlatResourceImage(
|
|
801
|
-
return
|
|
798
|
+
function isFlatResourceImage(path9) {
|
|
799
|
+
return path9.split("/").includes("Resources") && RASTER_EXTENSIONS.has(extOf(path9));
|
|
802
800
|
}
|
|
803
801
|
function enumerateBundleImages(paths, readText) {
|
|
804
802
|
const table = [];
|
|
805
803
|
const seen = /* @__PURE__ */ new Set();
|
|
806
|
-
const catalogs = paths.filter((
|
|
804
|
+
const catalogs = paths.filter((path9) => baseOf(path9) === "Contents.json");
|
|
807
805
|
for (const contentsPath of catalogs) {
|
|
808
806
|
const name = imagesetName(contentsPath);
|
|
809
807
|
if (name === null || seen.has(name)) continue;
|
|
@@ -823,12 +821,12 @@ function enumerateBundleImages(paths, readText) {
|
|
|
823
821
|
seen.add(name);
|
|
824
822
|
table.push({ name, file: `${dir}/${file}` });
|
|
825
823
|
}
|
|
826
|
-
for (const
|
|
827
|
-
if (!isFlatResourceImage(
|
|
828
|
-
const name = baseOf(
|
|
824
|
+
for (const path9 of paths) {
|
|
825
|
+
if (!isFlatResourceImage(path9)) continue;
|
|
826
|
+
const name = baseOf(path9).slice(0, -extOf(path9).length);
|
|
829
827
|
if (name === "" || seen.has(name)) continue;
|
|
830
828
|
seen.add(name);
|
|
831
|
-
table.push({ name, file:
|
|
829
|
+
table.push({ name, file: path9 });
|
|
832
830
|
}
|
|
833
831
|
return table;
|
|
834
832
|
}
|
|
@@ -836,7 +834,7 @@ function enumerateBundleJson(paths) {
|
|
|
836
834
|
const found = [];
|
|
837
835
|
const seen = /* @__PURE__ */ new Set();
|
|
838
836
|
const ordered = [...paths].filter(
|
|
839
|
-
(
|
|
837
|
+
(path9) => path9.split("/").includes("Resources") && path9.split("/").every((segment) => segment !== "" && segment !== "..") && extOf(path9) === ".json"
|
|
840
838
|
).sort((a, b) => {
|
|
841
839
|
const aDepth = a.split("/").length;
|
|
842
840
|
const bDepth = b.split("/").length;
|
|
@@ -851,20 +849,331 @@ function enumerateBundleJson(paths) {
|
|
|
851
849
|
return found;
|
|
852
850
|
}
|
|
853
851
|
|
|
854
|
-
// ../sootsim-swift/
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
}
|
|
852
|
+
// ../sootsim-swift/src/entryModule.ts
|
|
853
|
+
function swiftEntryModuleEsm(args) {
|
|
854
|
+
return [
|
|
855
|
+
`import { createSwiftEntry } from 'peachsim/swift'`,
|
|
856
|
+
`export default createSwiftEntry({ url: ${JSON.stringify(args.url)}, hash: ${JSON.stringify(args.hash)}, rootId: ${JSON.stringify(args.rootId)}, resources: ${JSON.stringify(args.resources)}, bundleFiles: ${JSON.stringify(args.bundleFiles)} })`,
|
|
857
|
+
""
|
|
858
|
+
].join("\n");
|
|
859
|
+
}
|
|
859
860
|
|
|
860
|
-
// src/
|
|
861
|
+
// src/swift-compile.ts
|
|
862
|
+
var import_node_child_process2 = require("node:child_process");
|
|
863
|
+
var import_node_crypto2 = require("node:crypto");
|
|
864
|
+
var import_node_fs3 = require("node:fs");
|
|
865
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
866
|
+
var import_node_util = require("node:util");
|
|
867
|
+
|
|
868
|
+
// src/swift-package.ts
|
|
869
|
+
function swiftManifestTargets(manifest) {
|
|
870
|
+
const code = manifest.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
|
|
871
|
+
const targets = [];
|
|
872
|
+
const pattern = /\.(executableTarget|target)\s*\(/g;
|
|
873
|
+
let match;
|
|
874
|
+
while ((match = pattern.exec(code)) !== null) {
|
|
875
|
+
const executable = match[1] === "executableTarget";
|
|
876
|
+
let depth = 1;
|
|
877
|
+
let i = pattern.lastIndex;
|
|
878
|
+
let inString = false;
|
|
879
|
+
let escaped = false;
|
|
880
|
+
let flat = "";
|
|
881
|
+
while (i < code.length && depth > 0) {
|
|
882
|
+
const ch = code[i];
|
|
883
|
+
if (inString) {
|
|
884
|
+
if (escaped) escaped = false;
|
|
885
|
+
else if (ch === "\\") escaped = true;
|
|
886
|
+
else if (ch === '"') inString = false;
|
|
887
|
+
if (depth === 1) flat += ch;
|
|
888
|
+
} else if (ch === '"') {
|
|
889
|
+
inString = true;
|
|
890
|
+
if (depth === 1) flat += ch;
|
|
891
|
+
} else if (ch === "(") {
|
|
892
|
+
depth++;
|
|
893
|
+
if (depth === 1) flat += ch;
|
|
894
|
+
} else if (ch === ")") {
|
|
895
|
+
depth--;
|
|
896
|
+
if (depth >= 1) flat += ch;
|
|
897
|
+
} else if (depth === 1) {
|
|
898
|
+
flat += ch;
|
|
899
|
+
}
|
|
900
|
+
i++;
|
|
901
|
+
}
|
|
902
|
+
const name = /\bname\s*:\s*"([^"]+)"/.exec(flat)?.[1];
|
|
903
|
+
if (!name) continue;
|
|
904
|
+
const rawPath = /\bpath\s*:\s*"([^"]*)"/.exec(flat)?.[1];
|
|
905
|
+
const targetPath = rawPath == null || rawPath === "" ? `Sources/${name}` : rawPath.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
906
|
+
targets.push({ name, path: targetPath, executable });
|
|
907
|
+
}
|
|
908
|
+
return targets;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// src/swift-compile.ts
|
|
861
912
|
var run = (0, import_node_util.promisify)(import_node_child_process2.execFile);
|
|
862
|
-
var TOOLCHAIN_BIN = import_node_path4.default.join(
|
|
863
|
-
import_node_os2.default.homedir(),
|
|
864
|
-
`Library/Developer/Toolchains/${toolchain_default.release}.xctoolchain/usr/bin`
|
|
865
|
-
);
|
|
866
|
-
var WASM_SDK = `${toolchain_default.release}_wasm`;
|
|
867
913
|
var WASM_TRIPLE = "wasm32-unknown-wasip1";
|
|
914
|
+
function swiftModuleInputFiles(root) {
|
|
915
|
+
const files = ["Package.swift", "scripts/contrast-app-Package.swift"];
|
|
916
|
+
const walk = (dir) => {
|
|
917
|
+
for (const entry of (0, import_node_fs3.readdirSync)(import_node_path4.default.join(root, dir), { withFileTypes: true })) {
|
|
918
|
+
const relative2 = `${dir}/${entry.name}`;
|
|
919
|
+
if (entry.isDirectory()) walk(relative2);
|
|
920
|
+
else if (entry.name.endsWith(".swift")) files.push(relative2);
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
walk("Sources");
|
|
924
|
+
return files.sort();
|
|
925
|
+
}
|
|
926
|
+
var linkedModuleDigests = /* @__PURE__ */ new Map();
|
|
927
|
+
function linkedModuleDigest(root) {
|
|
928
|
+
const files = swiftModuleInputFiles(root);
|
|
929
|
+
const stampHash = (0, import_node_crypto2.createHash)("sha256");
|
|
930
|
+
for (const file of files) {
|
|
931
|
+
const stat = (0, import_node_fs3.statSync)(import_node_path4.default.join(root, file), { bigint: true });
|
|
932
|
+
stampHash.update(file);
|
|
933
|
+
stampHash.update(
|
|
934
|
+
`${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}
|
|
935
|
+
`
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
const stamp = stampHash.digest("hex");
|
|
939
|
+
const cached = linkedModuleDigests.get(root);
|
|
940
|
+
if (cached?.stamp === stamp) return cached.digest;
|
|
941
|
+
const hash = (0, import_node_crypto2.createHash)("sha256");
|
|
942
|
+
for (const file of files) {
|
|
943
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
|
|
944
|
+
hash.update(
|
|
945
|
+
(0, import_node_crypto2.createHash)("sha256").update((0, import_node_fs3.readFileSync)(import_node_path4.default.join(root, file))).digest()
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
const digest = hash.digest();
|
|
949
|
+
linkedModuleDigests.set(root, { stamp, digest });
|
|
950
|
+
return digest;
|
|
951
|
+
}
|
|
952
|
+
function compileTargets(input) {
|
|
953
|
+
const manifest = input.files["Package.swift"];
|
|
954
|
+
return manifest === void 0 ? [] : swiftManifestTargets(manifest);
|
|
955
|
+
}
|
|
956
|
+
function swiftSiblingDependencies(files, targets) {
|
|
957
|
+
const names = new Set(targets.map((target) => target.name));
|
|
958
|
+
const siblings = /* @__PURE__ */ new Map();
|
|
959
|
+
for (const target of targets) {
|
|
960
|
+
const prefix = `${target.path}/`;
|
|
961
|
+
const deps = /* @__PURE__ */ new Set();
|
|
962
|
+
for (const [file, contents] of Object.entries(files)) {
|
|
963
|
+
if (file === "Package.swift" || !file.startsWith(prefix)) continue;
|
|
964
|
+
for (const match of contents.matchAll(/^\s*import\s+([A-Za-z_][A-Za-z0-9_]*)/gm)) {
|
|
965
|
+
if (names.has(match[1]) && match[1] !== target.name) deps.add(match[1]);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
siblings.set(target.name, [...deps].sort());
|
|
969
|
+
}
|
|
970
|
+
return siblings;
|
|
971
|
+
}
|
|
972
|
+
var MULTI_MANIFEST_VERSION = 1;
|
|
973
|
+
function swiftArtifactHash(input, release, moduleRoot) {
|
|
974
|
+
const hash = (0, import_node_crypto2.createHash)("sha256");
|
|
975
|
+
hash.update(`swift-compile/v1
|
|
976
|
+
${release}
|
|
977
|
+
`);
|
|
978
|
+
hash.update(linkedModuleDigest(moduleRoot));
|
|
979
|
+
for (const file of Object.keys(input.files).sort()) {
|
|
980
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
|
|
981
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(input.files[file]).digest());
|
|
982
|
+
}
|
|
983
|
+
for (const base of Object.keys(input.resources ?? {}).sort()) {
|
|
984
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(base).digest());
|
|
985
|
+
hash.update(
|
|
986
|
+
(0, import_node_crypto2.createHash)("sha256").update(input.resources?.[base] ?? "").digest()
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
for (const name of Object.keys(input.images ?? {}).sort()) {
|
|
990
|
+
const image = input.images?.[name];
|
|
991
|
+
if (!image) continue;
|
|
992
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(name).digest());
|
|
993
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(image.file).digest());
|
|
994
|
+
hash.update((0, import_node_crypto2.createHash)("sha256").update(image.data).digest());
|
|
995
|
+
}
|
|
996
|
+
const targets = compileTargets(input);
|
|
997
|
+
if (targets.length > 0) {
|
|
998
|
+
hash.update(`swift-multi/v${MULTI_MANIFEST_VERSION}
|
|
999
|
+
`);
|
|
1000
|
+
hash.update(
|
|
1001
|
+
JSON.stringify({
|
|
1002
|
+
targets,
|
|
1003
|
+
siblings: [...swiftSiblingDependencies(input.files, targets)].sort(
|
|
1004
|
+
(a, b) => String(a) < String(b) ? -1 : String(a) > String(b) ? 1 : 0
|
|
1005
|
+
)
|
|
1006
|
+
})
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
1009
|
+
return hash.digest("hex");
|
|
1010
|
+
}
|
|
1011
|
+
function emitSwiftPackageManifest(args) {
|
|
1012
|
+
const { targets, siblings, moduleRoot } = args;
|
|
1013
|
+
const executable = targets.find((target) => target.executable);
|
|
1014
|
+
if (!executable) throw new Error("swift-compile: no executable target to emit");
|
|
1015
|
+
const swiftSettings = 'swiftSettings: [.swiftLanguageMode(.v5), .unsafeFlags(["-Osize"])]';
|
|
1016
|
+
const stanza = (target) => {
|
|
1017
|
+
const deps = [
|
|
1018
|
+
'.product(name: "SwiftUI", package: "sootsim-swift")',
|
|
1019
|
+
...(siblings.get(target.name) ?? []).map((sibling) => `"${sibling}"`)
|
|
1020
|
+
].join(", ");
|
|
1021
|
+
const kind = target.executable ? ".executableTarget" : ".target";
|
|
1022
|
+
const link = target.executable ? `,
|
|
1023
|
+
linkerSettings: [
|
|
1024
|
+
.unsafeFlags([
|
|
1025
|
+
"-Xclang-linker", "-mexec-model=reactor",
|
|
1026
|
+
"-Xlinker", "--export-if-defined=__main_argc_argv",
|
|
1027
|
+
]),
|
|
1028
|
+
.unsafeFlags(["-Xlinker", "--strip-all"], .when(configuration: .release)),
|
|
1029
|
+
]` : "";
|
|
1030
|
+
return [
|
|
1031
|
+
` ${kind}(`,
|
|
1032
|
+
` name: "${target.name}",`,
|
|
1033
|
+
` dependencies: [${deps}],`,
|
|
1034
|
+
` path: "${target.path}",`,
|
|
1035
|
+
` ${swiftSettings}${link}`,
|
|
1036
|
+
` ),`
|
|
1037
|
+
].join("\n");
|
|
1038
|
+
};
|
|
1039
|
+
return [
|
|
1040
|
+
"// swift-tools-version: 6.0",
|
|
1041
|
+
"import PackageDescription",
|
|
1042
|
+
"",
|
|
1043
|
+
"// generated by swift-compile from the project package partition.",
|
|
1044
|
+
"let package = Package(",
|
|
1045
|
+
' name: "app",',
|
|
1046
|
+
` products: [.executable(name: "${executable.name}", targets: ["${executable.name}"])],`,
|
|
1047
|
+
` dependencies: [.package(path: "${moduleRoot}")],`,
|
|
1048
|
+
" targets: [",
|
|
1049
|
+
...targets.map(stanza),
|
|
1050
|
+
" ]",
|
|
1051
|
+
")",
|
|
1052
|
+
""
|
|
1053
|
+
].join("\n");
|
|
1054
|
+
}
|
|
1055
|
+
function writeSwiftProject(layout, input, moduleRoot) {
|
|
1056
|
+
const targets = compileTargets(input);
|
|
1057
|
+
if (targets.length === 0) {
|
|
1058
|
+
(0, import_node_fs3.rmSync)(layout.sources, { recursive: true, force: true });
|
|
1059
|
+
for (const [file, contents] of Object.entries(input.files)) {
|
|
1060
|
+
const target = import_node_path4.default.join(layout.sources, file);
|
|
1061
|
+
(0, import_node_fs3.mkdirSync)(import_node_path4.default.dirname(target), { recursive: true });
|
|
1062
|
+
(0, import_node_fs3.writeFileSync)(target, contents, "utf8");
|
|
1063
|
+
}
|
|
1064
|
+
const manifest = (0, import_node_fs3.readFileSync)(
|
|
1065
|
+
import_node_path4.default.join(moduleRoot, "scripts/contrast-app-Package.swift"),
|
|
1066
|
+
"utf8"
|
|
1067
|
+
).replaceAll("__SOOTSIM_SWIFT_PACKAGE__", moduleRoot);
|
|
1068
|
+
(0, import_node_fs3.writeFileSync)(import_node_path4.default.join(layout.root, "Package.swift"), manifest, "utf8");
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
(0, import_node_fs3.mkdirSync)(layout.root, { recursive: true });
|
|
1072
|
+
for (const child of (0, import_node_fs3.readdirSync)(layout.root)) {
|
|
1073
|
+
if (child === ".build") continue;
|
|
1074
|
+
(0, import_node_fs3.rmSync)(import_node_path4.default.join(layout.root, child), { recursive: true, force: true });
|
|
1075
|
+
}
|
|
1076
|
+
for (const [file, contents] of Object.entries(input.files)) {
|
|
1077
|
+
if (file === "Package.swift") continue;
|
|
1078
|
+
const target = import_node_path4.default.join(layout.root, file);
|
|
1079
|
+
(0, import_node_fs3.mkdirSync)(import_node_path4.default.dirname(target), { recursive: true });
|
|
1080
|
+
(0, import_node_fs3.writeFileSync)(target, contents, "utf8");
|
|
1081
|
+
}
|
|
1082
|
+
(0, import_node_fs3.writeFileSync)(
|
|
1083
|
+
import_node_path4.default.join(layout.root, "Package.swift"),
|
|
1084
|
+
emitSwiftPackageManifest({
|
|
1085
|
+
targets,
|
|
1086
|
+
siblings: swiftSiblingDependencies(input.files, targets),
|
|
1087
|
+
moduleRoot
|
|
1088
|
+
}),
|
|
1089
|
+
"utf8"
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
function streamText(value) {
|
|
1093
|
+
if (typeof value === "string") return value.trim();
|
|
1094
|
+
if (Buffer.isBuffer(value)) return value.toString("utf8").trim();
|
|
1095
|
+
return "";
|
|
1096
|
+
}
|
|
1097
|
+
function outputOf(error) {
|
|
1098
|
+
if (error && typeof error === "object") {
|
|
1099
|
+
const streams = [
|
|
1100
|
+
streamText(Reflect.get(error, "stdout")),
|
|
1101
|
+
streamText(Reflect.get(error, "stderr"))
|
|
1102
|
+
].filter(Boolean);
|
|
1103
|
+
if (streams.length > 0) return streams.join("\n");
|
|
1104
|
+
}
|
|
1105
|
+
return error instanceof Error ? error.message : String(error);
|
|
1106
|
+
}
|
|
1107
|
+
function builtArtifact(layout) {
|
|
1108
|
+
const binDir = import_node_path4.default.join(layout.root, ".build", WASM_TRIPLE, "release");
|
|
1109
|
+
const artifacts = (0, import_node_fs3.existsSync)(binDir) ? (0, import_node_fs3.readdirSync)(binDir).filter((name) => name.endsWith(".wasm")).sort() : [];
|
|
1110
|
+
if (artifacts.length !== 1) {
|
|
1111
|
+
throw new Error(
|
|
1112
|
+
`swift-compile: the build produced ${artifacts.length} wasm artifacts; exactly one executable is the app`
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
return import_node_path4.default.join(binDir, artifacts[0]);
|
|
1116
|
+
}
|
|
1117
|
+
function projectDiagnostic(output, layout) {
|
|
1118
|
+
const base = layout.multi ? layout.root : layout.sources;
|
|
1119
|
+
const prefix = `${base}${import_node_path4.default.sep}`;
|
|
1120
|
+
return output.split("\n").map((line) => line.startsWith(prefix) ? line.slice(prefix.length) : line).join("\n").trim();
|
|
1121
|
+
}
|
|
1122
|
+
var ROOT_LOCKS = Symbol.for("peachsim.swiftCompile.rootLocks");
|
|
1123
|
+
var host = globalThis;
|
|
1124
|
+
var rootLocks = host[ROOT_LOCKS] ??= /* @__PURE__ */ new Map();
|
|
1125
|
+
function serialize(root, work) {
|
|
1126
|
+
const current = rootLocks.get(root) ?? Promise.resolve();
|
|
1127
|
+
const next = current.then(work, work);
|
|
1128
|
+
rootLocks.set(
|
|
1129
|
+
root,
|
|
1130
|
+
next.catch(() => {
|
|
1131
|
+
})
|
|
1132
|
+
);
|
|
1133
|
+
return next;
|
|
1134
|
+
}
|
|
1135
|
+
function compileSwiftProjectUnit(input, options) {
|
|
1136
|
+
(0, import_node_fs3.mkdirSync)(options.buildRoot, { recursive: true });
|
|
1137
|
+
const root = (0, import_node_fs3.realpathSync)(options.buildRoot);
|
|
1138
|
+
const moduleRoot = import_node_path4.default.resolve(options.moduleRoot);
|
|
1139
|
+
const layout = {
|
|
1140
|
+
root,
|
|
1141
|
+
sources: import_node_path4.default.join(root, "Sources", "App"),
|
|
1142
|
+
multi: compileTargets(input).length > 0
|
|
1143
|
+
};
|
|
1144
|
+
const hash = swiftArtifactHash(input, options.release, moduleRoot);
|
|
1145
|
+
return serialize(root, async () => {
|
|
1146
|
+
writeSwiftProject(layout, input, moduleRoot);
|
|
1147
|
+
const swift = import_node_path4.default.join(options.toolchainBin, "swift");
|
|
1148
|
+
if (!(0, import_node_fs3.existsSync)(swift)) {
|
|
1149
|
+
throw new Error(
|
|
1150
|
+
`swift-compile: no swift.org toolchain at ${options.toolchainBin}; install ${options.release} and its matching wasm sdk`
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
try {
|
|
1154
|
+
await run(
|
|
1155
|
+
swift,
|
|
1156
|
+
[
|
|
1157
|
+
"build",
|
|
1158
|
+
"--package-path",
|
|
1159
|
+
root,
|
|
1160
|
+
"--swift-sdk",
|
|
1161
|
+
`${options.release}_wasm`,
|
|
1162
|
+
"-c",
|
|
1163
|
+
"release",
|
|
1164
|
+
"-Xswiftc",
|
|
1165
|
+
"-Osize"
|
|
1166
|
+
],
|
|
1167
|
+
{ maxBuffer: 64 * 1024 * 1024, timeout: options.timeoutMs }
|
|
1168
|
+
);
|
|
1169
|
+
} catch (error) {
|
|
1170
|
+
throw new Error(projectDiagnostic(outputOf(error), layout), { cause: error });
|
|
1171
|
+
}
|
|
1172
|
+
return { hash, bytes: (0, import_node_fs3.readFileSync)(builtArtifact(layout)) };
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
// src/vite-plugin-swift.ts
|
|
868
1177
|
var ARTIFACT_PATH = "/__rnx/swift/";
|
|
869
1178
|
var RESOURCE_PATH = "/__rnx/swift-res/";
|
|
870
1179
|
var VIRTUAL_PREFIX = "\0rnx-swift:";
|
|
@@ -885,11 +1194,11 @@ function projectFor(packagePath) {
|
|
|
885
1194
|
function sourceFiles(root) {
|
|
886
1195
|
const found = [];
|
|
887
1196
|
const walk = (dir) => {
|
|
888
|
-
for (const entry of
|
|
1197
|
+
for (const entry of import_node_fs4.default.readdirSync(dir, { withFileTypes: true })) {
|
|
889
1198
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
890
|
-
const full =
|
|
1199
|
+
const full = import_node_path5.default.join(dir, entry.name);
|
|
891
1200
|
if (entry.isDirectory()) {
|
|
892
|
-
if (full !== root &&
|
|
1201
|
+
if (full !== root && import_node_fs4.default.existsSync(import_node_path5.default.join(full, "Package.swift"))) continue;
|
|
893
1202
|
walk(full);
|
|
894
1203
|
} else if (entry.name.endsWith(".swift")) found.push(full);
|
|
895
1204
|
}
|
|
@@ -900,12 +1209,12 @@ function sourceFiles(root) {
|
|
|
900
1209
|
function resourceCandidateFiles(root) {
|
|
901
1210
|
const found = [];
|
|
902
1211
|
const walk = (dir) => {
|
|
903
|
-
for (const entry of
|
|
1212
|
+
for (const entry of import_node_fs4.default.readdirSync(dir, { withFileTypes: true })) {
|
|
904
1213
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === ".build")
|
|
905
1214
|
continue;
|
|
906
|
-
const full =
|
|
1215
|
+
const full = import_node_path5.default.join(dir, entry.name);
|
|
907
1216
|
if (entry.isDirectory()) {
|
|
908
|
-
if (full !== root &&
|
|
1217
|
+
if (full !== root && import_node_fs4.default.existsSync(import_node_path5.default.join(full, "Package.swift"))) continue;
|
|
909
1218
|
walk(full);
|
|
910
1219
|
} else {
|
|
911
1220
|
found.push(full);
|
|
@@ -928,19 +1237,20 @@ var RESOURCE_CONTENT_TYPES = {
|
|
|
928
1237
|
function buildSwiftResourceTable(project, baseUrl) {
|
|
929
1238
|
const absolute = resourceCandidateFiles(project.packagePath);
|
|
930
1239
|
const relative2 = absolute.map(
|
|
931
|
-
(file) =>
|
|
1240
|
+
(file) => import_node_path5.default.relative(project.packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep)
|
|
932
1241
|
);
|
|
933
1242
|
const byRelative = new Map(absolute.map((file, index) => [relative2[index], file]));
|
|
934
1243
|
const found = enumerateBundleImages(relative2, (candidate) => {
|
|
935
1244
|
const file = byRelative.get(candidate);
|
|
936
|
-
if (!file ||
|
|
1245
|
+
if (!file || import_node_path5.default.basename(file) !== "Contents.json") return null;
|
|
937
1246
|
try {
|
|
938
|
-
return
|
|
1247
|
+
return import_node_fs4.default.readFileSync(file, "utf8");
|
|
939
1248
|
} catch {
|
|
940
1249
|
return null;
|
|
941
1250
|
}
|
|
942
1251
|
});
|
|
943
1252
|
const table = {};
|
|
1253
|
+
const images = {};
|
|
944
1254
|
const watched = [];
|
|
945
1255
|
const registered = /* @__PURE__ */ new Map();
|
|
946
1256
|
for (const { name, file } of found) {
|
|
@@ -948,27 +1258,31 @@ function buildSwiftResourceTable(project, baseUrl) {
|
|
|
948
1258
|
if (!disk) continue;
|
|
949
1259
|
let bytes;
|
|
950
1260
|
try {
|
|
951
|
-
bytes =
|
|
1261
|
+
bytes = import_node_fs4.default.readFileSync(disk);
|
|
952
1262
|
} catch {
|
|
953
1263
|
continue;
|
|
954
1264
|
}
|
|
955
|
-
const hash = (0,
|
|
956
|
-
const ext =
|
|
1265
|
+
const hash = (0, import_node_crypto3.createHash)("sha256").update(bytes).digest("hex").slice(0, 16);
|
|
1266
|
+
const ext = import_node_path5.default.posix.extname(file).toLowerCase();
|
|
957
1267
|
table[name] = `${baseUrl}${RESOURCE_PATH}${hash}${ext}`;
|
|
1268
|
+
images[name] = {
|
|
1269
|
+
file: import_node_path5.default.posix.basename(file),
|
|
1270
|
+
data: bytes.toString("base64")
|
|
1271
|
+
};
|
|
958
1272
|
watched.push(file);
|
|
959
1273
|
const contents = file.replace(/\/[^/]+$/, "/Contents.json");
|
|
960
1274
|
if (byRelative.has(contents)) watched.push(contents);
|
|
961
1275
|
registered.set(`${hash}${ext}`, disk);
|
|
962
1276
|
}
|
|
963
1277
|
project.resourceFiles = registered;
|
|
964
|
-
return { table, watched };
|
|
1278
|
+
return { table, images, watched };
|
|
965
1279
|
}
|
|
966
1280
|
var BUNDLE_MAX_FILES = 128;
|
|
967
1281
|
var BUNDLE_MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
968
1282
|
var BUNDLE_MAX_TOTAL_BYTES = 8 * 1024 * 1024;
|
|
969
1283
|
function buildSwiftBundleFiles(packagePath) {
|
|
970
1284
|
const relative2 = resourceCandidateFiles(packagePath).map(
|
|
971
|
-
(file) =>
|
|
1285
|
+
(file) => import_node_path5.default.relative(packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep)
|
|
972
1286
|
);
|
|
973
1287
|
const files = {};
|
|
974
1288
|
const watched = [];
|
|
@@ -978,7 +1292,7 @@ function buildSwiftBundleFiles(packagePath) {
|
|
|
978
1292
|
watched.push(file);
|
|
979
1293
|
let bytes;
|
|
980
1294
|
try {
|
|
981
|
-
bytes =
|
|
1295
|
+
bytes = import_node_fs4.default.readFileSync(import_node_path5.default.join(packagePath, ...file.split("/")));
|
|
982
1296
|
} catch {
|
|
983
1297
|
continue;
|
|
984
1298
|
}
|
|
@@ -1002,8 +1316,8 @@ function serveSwiftResource(project, key) {
|
|
|
1002
1316
|
if (!disk) return null;
|
|
1003
1317
|
try {
|
|
1004
1318
|
return {
|
|
1005
|
-
bytes:
|
|
1006
|
-
contentType: RESOURCE_CONTENT_TYPES[
|
|
1319
|
+
bytes: import_node_fs4.default.readFileSync(disk),
|
|
1320
|
+
contentType: RESOURCE_CONTENT_TYPES[import_node_path5.default.extname(disk).toLowerCase()] ?? "application/octet-stream"
|
|
1007
1321
|
};
|
|
1008
1322
|
} catch {
|
|
1009
1323
|
return null;
|
|
@@ -1012,32 +1326,53 @@ function serveSwiftResource(project, key) {
|
|
|
1012
1326
|
function linkedModuleRoots(packagePath) {
|
|
1013
1327
|
let manifest;
|
|
1014
1328
|
try {
|
|
1015
|
-
manifest =
|
|
1329
|
+
manifest = import_node_fs4.default.readFileSync(import_node_path5.default.join(packagePath, "Package.swift"), "utf8");
|
|
1016
1330
|
} catch {
|
|
1017
1331
|
return [];
|
|
1018
1332
|
}
|
|
1019
1333
|
const roots = /* @__PURE__ */ new Set();
|
|
1020
1334
|
const dependency = /\.package\(\s*path:\s*"([^"]+)"\s*\)/g;
|
|
1021
1335
|
for (const match of manifest.replace(/^\s*\/\/.*$/gm, "").matchAll(dependency)) {
|
|
1022
|
-
const root =
|
|
1023
|
-
if (
|
|
1336
|
+
const root = import_node_path5.default.resolve(packagePath, match[1]);
|
|
1337
|
+
if (import_node_fs4.default.existsSync(import_node_path5.default.join(root, "Package.swift"))) roots.add(root);
|
|
1024
1338
|
}
|
|
1025
1339
|
return [...roots].sort();
|
|
1026
1340
|
}
|
|
1027
1341
|
function sourceStamp(packagePath) {
|
|
1028
|
-
const hash = (0,
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1342
|
+
const hash = (0, import_node_crypto3.createHash)("sha256");
|
|
1343
|
+
hash.update(packagePath);
|
|
1344
|
+
const projectInputs = /* @__PURE__ */ new Set([
|
|
1345
|
+
import_node_path5.default.join(packagePath, "Package.swift"),
|
|
1346
|
+
...sourceFiles(packagePath),
|
|
1347
|
+
...buildSwiftBundleFiles(packagePath).watched.map(
|
|
1348
|
+
(file) => import_node_path5.default.join(packagePath, ...file.split(import_node_path5.default.posix.sep))
|
|
1349
|
+
),
|
|
1350
|
+
...buildSwiftResourceTable(projectFor(packagePath), "").watched.map(
|
|
1351
|
+
(file) => import_node_path5.default.join(packagePath, ...file.split(import_node_path5.default.posix.sep))
|
|
1352
|
+
)
|
|
1353
|
+
]);
|
|
1354
|
+
for (const file of [...projectInputs].sort()) {
|
|
1355
|
+
hash.update(import_node_path5.default.relative(packagePath, file));
|
|
1356
|
+
hash.update(String(import_node_fs4.default.statSync(file).mtimeMs));
|
|
1357
|
+
}
|
|
1358
|
+
const moduleRoot = linkedModuleRoots(packagePath).find(
|
|
1359
|
+
(root) => import_node_fs4.default.existsSync(import_node_path5.default.join(root, "toolchain.json"))
|
|
1360
|
+
);
|
|
1361
|
+
if (moduleRoot) {
|
|
1362
|
+
hash.update(moduleRoot);
|
|
1363
|
+
for (const relative2 of [
|
|
1364
|
+
...swiftModuleInputFiles(moduleRoot),
|
|
1365
|
+
"toolchain.json"
|
|
1366
|
+
].sort()) {
|
|
1367
|
+
hash.update(relative2);
|
|
1368
|
+
hash.update(String(import_node_fs4.default.statSync(import_node_path5.default.join(moduleRoot, relative2)).mtimeMs));
|
|
1034
1369
|
}
|
|
1035
1370
|
}
|
|
1036
1371
|
return hash.digest("hex").slice(0, 16);
|
|
1037
1372
|
}
|
|
1038
1373
|
function entryRootId(packagePath, file) {
|
|
1039
|
-
const relative2 =
|
|
1040
|
-
return `${
|
|
1374
|
+
const relative2 = import_node_path5.default.relative(packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep);
|
|
1375
|
+
return `${import_node_path5.default.basename(packagePath)}${import_node_path5.default.posix.sep}${relative2}`;
|
|
1041
1376
|
}
|
|
1042
1377
|
function serverOrigin() {
|
|
1043
1378
|
const address = devServer?.httpServer?.address();
|
|
@@ -1048,70 +1383,60 @@ function serverOrigin() {
|
|
|
1048
1383
|
function artifactUrl(project, artifact) {
|
|
1049
1384
|
return `${serverOrigin()}${ARTIFACT_PATH}${artifact.hash}.wasm`;
|
|
1050
1385
|
}
|
|
1051
|
-
function
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
`swift project ${packagePath} built ${artifacts.length} wasm artifacts; exactly one executable is the app`
|
|
1057
|
-
);
|
|
1386
|
+
function compileInput(packagePath, entry) {
|
|
1387
|
+
const files = {};
|
|
1388
|
+
for (const file of sourceFiles(packagePath)) {
|
|
1389
|
+
const relative2 = import_node_path5.default.relative(packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep);
|
|
1390
|
+
files[relative2] = import_node_fs4.default.readFileSync(file, "utf8");
|
|
1058
1391
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1392
|
+
const manifest = import_node_path5.default.join(packagePath, "Package.swift");
|
|
1393
|
+
if (import_node_fs4.default.existsSync(manifest)) files["Package.swift"] = import_node_fs4.default.readFileSync(manifest, "utf8");
|
|
1394
|
+
const resources = buildSwiftBundleFiles(packagePath).files;
|
|
1395
|
+
const images = buildSwiftResourceTable(projectFor(packagePath), "").images;
|
|
1396
|
+
return {
|
|
1397
|
+
files,
|
|
1398
|
+
resources,
|
|
1399
|
+
images,
|
|
1400
|
+
entry
|
|
1401
|
+
};
|
|
1065
1402
|
}
|
|
1066
|
-
async function compile(packagePath, stamp) {
|
|
1067
|
-
const
|
|
1068
|
-
|
|
1403
|
+
async function compile(packagePath, entry, stamp) {
|
|
1404
|
+
const moduleRoot = linkedModuleRoots(packagePath).find(
|
|
1405
|
+
(root) => import_node_fs4.default.existsSync(import_node_path5.default.join(root, "toolchain.json"))
|
|
1406
|
+
);
|
|
1407
|
+
if (!moduleRoot) {
|
|
1069
1408
|
throw new Error(
|
|
1070
|
-
`
|
|
1409
|
+
`swift project ${packagePath} has no linked rnx SwiftUI package with toolchain.json`
|
|
1071
1410
|
);
|
|
1072
1411
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
packagePath,
|
|
1080
|
-
"--swift-sdk",
|
|
1081
|
-
WASM_SDK,
|
|
1082
|
-
"-c",
|
|
1083
|
-
"release",
|
|
1084
|
-
"-Xswiftc",
|
|
1085
|
-
"-Osize"
|
|
1086
|
-
],
|
|
1087
|
-
{ maxBuffer: 64 * 1024 * 1024 }
|
|
1088
|
-
);
|
|
1089
|
-
} catch (error) {
|
|
1090
|
-
const streams = error && typeof error === "object" ? [
|
|
1091
|
-
streamText(Reflect.get(error, "stdout")),
|
|
1092
|
-
streamText(Reflect.get(error, "stderr"))
|
|
1093
|
-
].filter(Boolean) : [];
|
|
1094
|
-
const detail = streams.length > 0 ? streams.join("\n") : error instanceof Error ? error.message : String(error);
|
|
1095
|
-
throw new Error(`swift build failed for ${packagePath}
|
|
1096
|
-
${detail}`);
|
|
1412
|
+
const toolchain = JSON.parse(
|
|
1413
|
+
import_node_fs4.default.readFileSync(import_node_path5.default.join(moduleRoot, "toolchain.json"), "utf8")
|
|
1414
|
+
);
|
|
1415
|
+
const release = toolchain && typeof toolchain === "object" ? Reflect.get(toolchain, "release") : void 0;
|
|
1416
|
+
if (typeof release !== "string") {
|
|
1417
|
+
throw new Error(`swift toolchain manifest at ${moduleRoot} has no release`);
|
|
1097
1418
|
}
|
|
1098
|
-
const
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1419
|
+
const artifact = await compileSwiftProjectUnit(compileInput(packagePath, entry), {
|
|
1420
|
+
buildRoot: process.env.CONTRAST_SWIFT_BUILD_ROOT ?? import_node_path5.default.join(import_node_os2.default.tmpdir(), "contrast-swift-build"),
|
|
1421
|
+
moduleRoot,
|
|
1422
|
+
release,
|
|
1423
|
+
toolchainBin: import_node_path5.default.join(
|
|
1424
|
+
import_node_os2.default.homedir(),
|
|
1425
|
+
`Library/Developer/Toolchains/${release}.xctoolchain/usr/bin`
|
|
1426
|
+
)
|
|
1427
|
+
});
|
|
1428
|
+
return { ...artifact, stamp };
|
|
1104
1429
|
}
|
|
1105
|
-
function artifactFor(project) {
|
|
1430
|
+
function artifactFor(project, entry) {
|
|
1106
1431
|
const stamp = sourceStamp(project.packagePath);
|
|
1107
1432
|
if (project.artifact?.stamp === stamp) return Promise.resolve(project.artifact);
|
|
1108
1433
|
if (project.building) {
|
|
1109
1434
|
const running = project.building;
|
|
1110
1435
|
if (running.stamp === stamp) return running.promise;
|
|
1111
|
-
const again = () => artifactFor(project);
|
|
1436
|
+
const again = () => artifactFor(project, entry);
|
|
1112
1437
|
return running.promise.then(again, again);
|
|
1113
1438
|
}
|
|
1114
|
-
const promise = compile(project.packagePath, stamp).then(
|
|
1439
|
+
const promise = compile(project.packagePath, entry, stamp).then(
|
|
1115
1440
|
(artifact) => {
|
|
1116
1441
|
project.artifact = artifact;
|
|
1117
1442
|
project.building = null;
|
|
@@ -1126,12 +1451,12 @@ function artifactFor(project) {
|
|
|
1126
1451
|
return promise;
|
|
1127
1452
|
}
|
|
1128
1453
|
function packageFor(file) {
|
|
1129
|
-
let dir =
|
|
1454
|
+
let dir = import_node_path5.default.dirname(file);
|
|
1130
1455
|
const stop = devServer?.config.root;
|
|
1131
1456
|
for (; ; ) {
|
|
1132
|
-
if (
|
|
1133
|
-
if (stop !== void 0 && dir === stop ||
|
|
1134
|
-
dir =
|
|
1457
|
+
if (import_node_fs4.default.existsSync(import_node_path5.default.join(dir, "Package.swift"))) return dir;
|
|
1458
|
+
if (stop !== void 0 && dir === stop || import_node_path5.default.dirname(dir) === dir) break;
|
|
1459
|
+
dir = import_node_path5.default.dirname(dir);
|
|
1135
1460
|
}
|
|
1136
1461
|
throw new Error(
|
|
1137
1462
|
`no Package.swift above ${file}${stop === void 0 ? "" : ` (searched up to ${stop})`}; a .swift import needs a swiftpm package like the one in packages/sootsim-swift/example`
|
|
@@ -1155,16 +1480,18 @@ function swiftPlugin(options = {}) {
|
|
|
1155
1480
|
async load(id) {
|
|
1156
1481
|
if (!id.startsWith(VIRTUAL_PREFIX)) return null;
|
|
1157
1482
|
const file = id.slice(VIRTUAL_PREFIX.length);
|
|
1158
|
-
if (!
|
|
1483
|
+
if (!import_node_fs4.default.existsSync(file)) throw new Error(`swift source ${file} no longer exists`);
|
|
1159
1484
|
const packagePath = options.packagePath ?? packageFor(file);
|
|
1160
1485
|
const project = projectFor(packagePath);
|
|
1486
|
+
const entry = import_node_path5.default.relative(packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep);
|
|
1161
1487
|
for (const source of sourceFiles(packagePath)) this.addWatchFile(source);
|
|
1488
|
+
this.addWatchFile(import_node_path5.default.join(packagePath, "Package.swift"));
|
|
1162
1489
|
for (const root of linkedModuleRoots(packagePath)) {
|
|
1163
1490
|
for (const source of sourceFiles(root)) this.addWatchFile(source);
|
|
1164
1491
|
}
|
|
1165
1492
|
let artifact;
|
|
1166
1493
|
try {
|
|
1167
|
-
artifact = await artifactFor(project);
|
|
1494
|
+
artifact = await artifactFor(project, entry);
|
|
1168
1495
|
} catch (error) {
|
|
1169
1496
|
if (!project.artifact) throw error;
|
|
1170
1497
|
this.warn(error instanceof Error ? error.message : String(error));
|
|
@@ -1174,7 +1501,9 @@ function swiftPlugin(options = {}) {
|
|
|
1174
1501
|
try {
|
|
1175
1502
|
const built = buildSwiftResourceTable(project, serverOrigin());
|
|
1176
1503
|
resources = built.table;
|
|
1177
|
-
for (const watched of built.watched)
|
|
1504
|
+
for (const watched of built.watched) {
|
|
1505
|
+
this.addWatchFile(import_node_path5.default.join(packagePath, ...watched.split(import_node_path5.default.posix.sep)));
|
|
1506
|
+
}
|
|
1178
1507
|
} catch (error) {
|
|
1179
1508
|
this.warn(
|
|
1180
1509
|
`swift resources for ${packagePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -1185,7 +1514,7 @@ function swiftPlugin(options = {}) {
|
|
|
1185
1514
|
const packed = buildSwiftBundleFiles(packagePath);
|
|
1186
1515
|
bundleFiles = packed.files;
|
|
1187
1516
|
for (const watched of packed.watched) {
|
|
1188
|
-
this.addWatchFile(
|
|
1517
|
+
this.addWatchFile(import_node_path5.default.join(packagePath, ...watched.split(import_node_path5.default.posix.sep)));
|
|
1189
1518
|
}
|
|
1190
1519
|
if (packed.skipped.length > 0) {
|
|
1191
1520
|
this.warn(
|
|
@@ -1197,11 +1526,13 @@ function swiftPlugin(options = {}) {
|
|
|
1197
1526
|
`swift bundle files for ${packagePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
1198
1527
|
);
|
|
1199
1528
|
}
|
|
1200
|
-
return
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1529
|
+
return swiftEntryModuleEsm({
|
|
1530
|
+
url: artifactUrl(project, artifact),
|
|
1531
|
+
hash: artifact.hash,
|
|
1532
|
+
rootId: entryRootId(packagePath, file),
|
|
1533
|
+
resources,
|
|
1534
|
+
bundleFiles
|
|
1535
|
+
});
|
|
1205
1536
|
},
|
|
1206
1537
|
configureServer(server) {
|
|
1207
1538
|
devServer = server;
|
|
@@ -1242,8 +1573,8 @@ function swiftPlugin(options = {}) {
|
|
|
1242
1573
|
}
|
|
1243
1574
|
|
|
1244
1575
|
// src/rolldown-plugin-swift.ts
|
|
1245
|
-
var
|
|
1246
|
-
var
|
|
1576
|
+
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
1577
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
1247
1578
|
|
|
1248
1579
|
// src/swift-submit.ts
|
|
1249
1580
|
var SWIFT_COMPILE_PATH = "/api/swift-compile";
|
|
@@ -1317,15 +1648,15 @@ function projectFor2(packagePath) {
|
|
|
1317
1648
|
function packageFiles(root) {
|
|
1318
1649
|
const found = [];
|
|
1319
1650
|
const walk = (dir) => {
|
|
1320
|
-
for (const entry of
|
|
1651
|
+
for (const entry of import_node_fs5.default.readdirSync(dir, { withFileTypes: true })) {
|
|
1321
1652
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === ".build")
|
|
1322
1653
|
continue;
|
|
1323
|
-
const full =
|
|
1654
|
+
const full = import_node_path6.default.join(dir, entry.name);
|
|
1324
1655
|
if (entry.isDirectory()) {
|
|
1325
|
-
if (full !== root &&
|
|
1656
|
+
if (full !== root && import_node_fs5.default.existsSync(import_node_path6.default.join(full, "Package.swift"))) continue;
|
|
1326
1657
|
walk(full);
|
|
1327
1658
|
} else {
|
|
1328
|
-
found.push(
|
|
1659
|
+
found.push(import_node_path6.default.relative(root, full).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep));
|
|
1329
1660
|
}
|
|
1330
1661
|
}
|
|
1331
1662
|
};
|
|
@@ -1336,8 +1667,8 @@ function sourceFiles2(packagePath) {
|
|
|
1336
1667
|
const files = {};
|
|
1337
1668
|
for (const relative2 of packageFiles(packagePath)) {
|
|
1338
1669
|
if (!relative2.endsWith(".swift")) continue;
|
|
1339
|
-
files[relative2] =
|
|
1340
|
-
|
|
1670
|
+
files[relative2] = import_node_fs5.default.readFileSync(
|
|
1671
|
+
import_node_path6.default.join(packagePath, ...relative2.split("/")),
|
|
1341
1672
|
"utf8"
|
|
1342
1673
|
);
|
|
1343
1674
|
}
|
|
@@ -1345,20 +1676,20 @@ function sourceFiles2(packagePath) {
|
|
|
1345
1676
|
}
|
|
1346
1677
|
function bundlePack(packagePath) {
|
|
1347
1678
|
const relative2 = packageFiles(packagePath);
|
|
1348
|
-
const disk = (file) =>
|
|
1679
|
+
const disk = (file) => import_node_path6.default.join(packagePath, ...file.split("/"));
|
|
1349
1680
|
const resources = {};
|
|
1350
1681
|
const watched = [];
|
|
1351
1682
|
for (const { base, file } of enumerateBundleJson(relative2)) {
|
|
1352
|
-
resources[base] =
|
|
1683
|
+
resources[base] = import_node_fs5.default.readFileSync(disk(file)).toString("base64");
|
|
1353
1684
|
watched.push(file);
|
|
1354
1685
|
}
|
|
1355
1686
|
const images = {};
|
|
1356
1687
|
const byRelative = new Map(relative2.map((file) => [file, disk(file)]));
|
|
1357
1688
|
for (const { name, file } of enumerateBundleImages(relative2, (candidate) => {
|
|
1358
1689
|
const absolute = byRelative.get(candidate);
|
|
1359
|
-
if (!absolute ||
|
|
1690
|
+
if (!absolute || import_node_path6.default.basename(absolute) !== "Contents.json") return null;
|
|
1360
1691
|
try {
|
|
1361
|
-
return
|
|
1692
|
+
return import_node_fs5.default.readFileSync(absolute, "utf8");
|
|
1362
1693
|
} catch {
|
|
1363
1694
|
return null;
|
|
1364
1695
|
}
|
|
@@ -1366,19 +1697,19 @@ function bundlePack(packagePath) {
|
|
|
1366
1697
|
const absolute = byRelative.get(file);
|
|
1367
1698
|
if (!absolute) continue;
|
|
1368
1699
|
images[name] = {
|
|
1369
|
-
file:
|
|
1370
|
-
data:
|
|
1700
|
+
file: import_node_path6.default.posix.basename(file),
|
|
1701
|
+
data: import_node_fs5.default.readFileSync(absolute).toString("base64")
|
|
1371
1702
|
};
|
|
1372
1703
|
watched.push(file);
|
|
1373
1704
|
}
|
|
1374
1705
|
return { resources, images, watched };
|
|
1375
1706
|
}
|
|
1376
1707
|
function packageFor2(file, stop) {
|
|
1377
|
-
let dir =
|
|
1708
|
+
let dir = import_node_path6.default.dirname(file);
|
|
1378
1709
|
for (; ; ) {
|
|
1379
|
-
if (
|
|
1380
|
-
if (stop !== void 0 && dir === stop ||
|
|
1381
|
-
dir =
|
|
1710
|
+
if (import_node_fs5.default.existsSync(import_node_path6.default.join(dir, "Package.swift"))) return dir;
|
|
1711
|
+
if (stop !== void 0 && dir === stop || import_node_path6.default.dirname(dir) === dir) break;
|
|
1712
|
+
dir = import_node_path6.default.dirname(dir);
|
|
1382
1713
|
}
|
|
1383
1714
|
throw new Error(
|
|
1384
1715
|
`no Package.swift above ${file}; a .swift import needs a swiftpm package like the one in packages/sootsim-swift/example`
|
|
@@ -1407,17 +1738,17 @@ function swiftRemotePlugin(options) {
|
|
|
1407
1738
|
async load(id) {
|
|
1408
1739
|
if (!id.startsWith(VIRTUAL_PREFIX2)) return null;
|
|
1409
1740
|
const file = id.slice(VIRTUAL_PREFIX2.length);
|
|
1410
|
-
if (!
|
|
1741
|
+
if (!import_node_fs5.default.existsSync(file)) throw new Error(`swift source ${file} no longer exists`);
|
|
1411
1742
|
const packagePath = options.packagePath ?? packageFor2(file);
|
|
1412
1743
|
const project = projectFor2(packagePath);
|
|
1413
1744
|
const files = sourceFiles2(packagePath);
|
|
1414
|
-
const entry =
|
|
1745
|
+
const entry = import_node_path6.default.relative(packagePath, file).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep);
|
|
1415
1746
|
for (const source of Object.keys(files)) {
|
|
1416
|
-
this.addWatchFile(
|
|
1747
|
+
this.addWatchFile(import_node_path6.default.join(packagePath, ...source.split("/")));
|
|
1417
1748
|
}
|
|
1418
1749
|
const pack = bundlePack(packagePath);
|
|
1419
1750
|
for (const watched of pack.watched) {
|
|
1420
|
-
this.addWatchFile(
|
|
1751
|
+
this.addWatchFile(import_node_path6.default.join(packagePath, ...watched.split("/")));
|
|
1421
1752
|
}
|
|
1422
1753
|
try {
|
|
1423
1754
|
project.address = await compileSwiftProject(
|
|
@@ -1430,11 +1761,13 @@ function swiftRemotePlugin(options) {
|
|
|
1430
1761
|
this.warn(error instanceof Error ? error.message : String(error));
|
|
1431
1762
|
}
|
|
1432
1763
|
const address = project.address;
|
|
1433
|
-
return
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1764
|
+
return swiftEntryModuleEsm({
|
|
1765
|
+
url: address.url,
|
|
1766
|
+
hash: address.hash,
|
|
1767
|
+
rootId: entryRootId(packagePath, file),
|
|
1768
|
+
resources: address.imageUrls ?? {},
|
|
1769
|
+
bundleFiles: pack.resources
|
|
1770
|
+
});
|
|
1438
1771
|
}
|
|
1439
1772
|
};
|
|
1440
1773
|
}
|
|
@@ -1459,7 +1792,7 @@ function rnxPlugin(options = {}) {
|
|
|
1459
1792
|
if (options.enabled === false) return;
|
|
1460
1793
|
const bundleUrl = options.bundleUrl || "/node_modules/one/metro-entry.bundle?platform=ios&dev=true&minify=false";
|
|
1461
1794
|
const appName = resolveRnxDesktopAppName(options.open, server.config.root);
|
|
1462
|
-
const replacementToken = (0,
|
|
1795
|
+
const replacementToken = (0, import_node_crypto4.randomUUID)();
|
|
1463
1796
|
const configuredPort = server.config.server.port || 8081;
|
|
1464
1797
|
const listeningPort = () => {
|
|
1465
1798
|
const address = server.httpServer?.address();
|