crossbind 2.0.0-beta.63 → 2.0.0-beta.65

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 (77) hide show
  1. package/AGENTS.md +2 -1
  2. package/package.json +2 -2
  3. package/src/actions/androidDevice.js +77 -0
  4. package/src/actions/androidGradle.js +121 -0
  5. package/src/actions/buildApp.js +434 -0
  6. package/src/actions/buildBinTools.js +0 -0
  7. package/src/actions/buildDependencies.js +4 -3
  8. package/src/actions/buildExternal.js +3 -3
  9. package/src/actions/buildJs.js +2 -9
  10. package/src/actions/buildLib.js +1 -1
  11. package/src/actions/buildNode.js +19 -16
  12. package/src/actions/buildWasiCommand.js +10 -5
  13. package/src/actions/buildWasm.js +24 -3
  14. package/src/actions/createImportedBridges.js +7 -0
  15. package/src/actions/createInterface.js +4 -5
  16. package/src/actions/createLib.js +17 -2
  17. package/src/actions/getCmakeParameters.js +2 -1
  18. package/src/actions/getData.js +2 -1
  19. package/src/actions/getDependLibs.js +8 -2
  20. package/src/actions/getEnv.js +7 -0
  21. package/src/actions/getLinkInputs.js +10 -7
  22. package/src/actions/gradleProject.js +110 -0
  23. package/src/actions/iosSimulator.js +63 -0
  24. package/src/actions/licenses.js +160 -14
  25. package/src/actions/nativeBridges.js +35 -0
  26. package/src/actions/run.js +3 -3
  27. package/src/actions/runnerCommands.js +16 -4
  28. package/src/actions/target.js +2 -1
  29. package/src/actions/writeRuntimeEntry.js +18 -7
  30. package/src/actions/xcodeProject.js +152 -0
  31. package/src/assets/cpp-runtime/node.cpp +18 -1
  32. package/src/assets/js-runtime/adapters/worker-comlink.js +58 -0
  33. package/src/assets/js-runtime/core.js +5 -4
  34. package/src/assets/toolchain-digests.json +25 -19
  35. package/src/assets/wasi-runtime/http/README.md +17 -0
  36. package/src/assets/wasi-runtime/http/bindings/crossbind_http.c +2537 -0
  37. package/src/assets/wasi-runtime/http/bindings/crossbind_http.h +826 -0
  38. package/src/assets/wasi-runtime/http/bindings/crossbind_http_component_type.o +0 -0
  39. package/src/assets/wasi-runtime/http/handler.cpp +298 -0
  40. package/src/assets/wasi-runtime/http/include/crossbind/http.h +31 -0
  41. package/src/assets/wasi-runtime/http/wit/deps/LICENSE.md +8 -0
  42. package/src/assets/wasi-runtime/http/wit/deps/cli.wit +28 -0
  43. package/src/assets/wasi-runtime/http/wit/deps/clocks.wit +43 -0
  44. package/src/assets/wasi-runtime/http/wit/deps/http.wit +509 -0
  45. package/src/assets/wasi-runtime/http/wit/deps/random.wit +18 -0
  46. package/src/assets/wasi-runtime/http/wit/world.wit +6 -0
  47. package/src/bin.js +102 -209
  48. package/src/cli.js +14 -0
  49. package/src/index.js +6 -0
  50. package/src/integration/getCrossbindScript.js +19 -4
  51. package/src/program.js +169 -0
  52. package/src/state/index.js +8 -3
  53. package/src/state/loadConfig.js +6 -11
  54. package/src/utils/appRustCrates.js +7 -1
  55. package/src/utils/bridgeExtras.js +74 -6
  56. package/src/utils/cargoLock.js +19 -0
  57. package/src/utils/cppDts.js +2 -0
  58. package/src/utils/downloadAndExtractFile.js +42 -14
  59. package/src/utils/embindObjectLifetime.js +35 -0
  60. package/src/utils/embindRsFingerprint.js +10 -3
  61. package/src/utils/hermes.js +40 -0
  62. package/src/utils/packageLicense.js +4 -2
  63. package/src/utils/plist.js +42 -0
  64. package/src/utils/pullDockerImage.js +9 -3
  65. package/src/utils/replaceBasePathForDocker.js +8 -0
  66. package/src/utils/resetCMakeCacheForSource.js +26 -0
  67. package/src/utils/resolveAppHost.js +21 -0
  68. package/src/utils/rustBridgeGen.js +13 -4
  69. package/src/utils/rustMt.js +5 -0
  70. package/src/utils/rustSysroot.js +7 -5
  71. package/src/utils/selectRunner.js +1 -1
  72. package/src/utils/swigInterface.js +5 -4
  73. package/src/utils/systemConfig.js +13 -0
  74. package/src/utils/systemKeys.js +4 -0
  75. package/src/utils/targets.js +30 -3
  76. package/src/utils/wasiHttp.js +50 -0
  77. package/vitest.config.js +5 -0
@@ -24,12 +24,48 @@ let nextEmbindId = 1;
24
24
  const HANDLES = '__crossbindHandles';
25
25
  let remoteModule = null;
26
26
 
27
+ // How many ids name each object, as a raw pointer handed out twice is one object.
28
+ const holders = new WeakMap();
29
+
27
30
  function registerEmbindObject(obj) {
28
31
  const id = nextEmbindId++;
29
32
  embindRegistry.set(id, obj);
33
+ holders.set(obj, (holders.get(obj) ?? 0) + 1);
30
34
  return id;
31
35
  }
32
36
 
37
+ // What JavaScript owns: an object behind a smart pointer, or a copy embind made of a returned value or an object
38
+ // JavaScript constructed, which utils/embindObjectLifetime.js marks. A raw pointer stays its library's.
39
+ const ownsObject = (obj) => {
40
+ const $$ = obj?.$$;
41
+ return Boolean($$ && ($$.smartPtr || $$.count?.owned));
42
+ };
43
+
44
+ // The module's own objects, its globals above all, live as long as the module, so letting go of a handle to one
45
+ // frees nothing.
46
+ const moduleObjects = new WeakSet();
47
+
48
+ const freeIfOwned = (obj) => {
49
+ if (ownsObject(obj) && !moduleObjects.has(obj) && !obj.isDeleted()) obj.delete();
50
+ };
51
+
52
+ // The worker side of a handle the main thread no longer reaches: its id goes, and the object with the last id.
53
+ const RELEASE = '__crossbindRelease';
54
+
55
+ function releaseEmbindObjects(ids) {
56
+ for (const id of ids) {
57
+ const obj = embindRegistry.get(id);
58
+ if (!embindRegistry.delete(id)) continue;
59
+ const left = holders.get(obj) - 1;
60
+ if (left > 0) {
61
+ holders.set(obj, left);
62
+ } else {
63
+ holders.delete(obj);
64
+ freeIfOwned(obj);
65
+ }
66
+ }
67
+ }
68
+
33
69
  // Comlink answers every member with a remote one: JSON.stringify and String() called toJSON and Symbol.toPrimitive
34
70
  // on the worker's object, which has neither, and a member below the module is thenable. A handle answers them as a
35
71
  // direct-mode object does.
@@ -39,11 +75,27 @@ const LOCAL_MEMBERS = {
39
75
  [Symbol.toPrimitive]: (hint) => (hint === 'number' ? NaN : '[object Object]'),
40
76
  };
41
77
 
78
+ // The main thread side: once a handle is collected, the worker lets go of its object, the ids collected in one task
79
+ // in one message.
80
+ const collected = [];
81
+
82
+ function releaseLater(id) {
83
+ collected.push(id);
84
+ if (collected.length > 1) return;
85
+ setTimeout(() => {
86
+ const ids = collected.splice(0);
87
+ Promise.resolve(remoteModule?.[RELEASE](ids)).catch(() => {});
88
+ }, 0);
89
+ }
90
+
91
+ const handleWatcher = typeof FinalizationRegistry === 'function' ? new FinalizationRegistry(releaseLater) : null;
92
+
42
93
  function handleFor(id) {
43
94
  const handle = new Proxy(remoteModule[HANDLES][id], {
44
95
  get: (target, prop) => (Object.hasOwn(LOCAL_MEMBERS, prop) ? LOCAL_MEMBERS[prop] : target[prop]),
45
96
  });
46
97
  embindProxyIds.set(handle, id);
98
+ handleWatcher?.register(handle, id);
47
99
  return handle;
48
100
  }
49
101
 
@@ -126,6 +178,8 @@ Comlink.transferHandlers.set('embindVector', {
126
178
  ? { __comlinkProxy: true, __embindId: registerEmbindObject(elem) }
127
179
  : elem;
128
180
  }
181
+ // The main thread gets the array alone, so nothing can reach a vector the call handed over any more.
182
+ freeIfOwned(unwrapCoercionProxy(obj));
129
183
  return [elements, []];
130
184
  },
131
185
  deserialize(elements) {
@@ -246,6 +300,10 @@ export function moduleRoot(m) {
246
300
  value: new Proxy({}, { get: (_, id) => embindRegistry.get(Number(id)) }),
247
301
  configurable: true,
248
302
  });
303
+ Object.defineProperty(m, RELEASE, { value: releaseEmbindObjects, configurable: true });
304
+ Object.values(m).forEach((value) => {
305
+ if (value !== null && typeof value === 'object') moduleObjects.add(value);
306
+ });
249
307
  return wrapWithVectorCoercion(m);
250
308
  }
251
309
 
@@ -74,12 +74,13 @@ function buildLocateFile(config, adapter) {
74
74
  }
75
75
 
76
76
  // WASMFS's FS.writeFile writes at the end of a file that exists (emsdk 6.0.9 js_api.cpp), where the classic FS
77
- // replaces it; opening the file for writing empties it first.
77
+ // replaces it; opening the file for writing empties it first, unless the flags ask to append.
78
78
  function replaceOnWriteFile(FS) {
79
79
  const { writeFile } = FS;
80
- FS.writeFile = (path, data) => {
81
- FS.close(FS.open(path, 'w'));
82
- return writeFile(path, data);
80
+ FS.writeFile = (path, data, opts) => {
81
+ const appends = typeof opts?.flags === 'string' && opts.flags.startsWith('a');
82
+ if (!appends) FS.close(FS.open(path, 'w', opts?.mode));
83
+ return writeFile(path, data, opts);
83
84
  };
84
85
  }
85
86
 
@@ -1,49 +1,55 @@
1
1
  {
2
- "version": "1.0.12",
2
+ "version": "1.0.15",
3
3
  "registry": "ghcr.io/crossbind",
4
4
  "toolchains": {
5
- "rust": "1.99.0"
5
+ "rust": "1.99.1"
6
6
  },
7
7
  "images": {
8
8
  "rust-sysroot": {
9
- "index": "sha256:fcaddb9514956c80c28152679d11817599b3c544e2bb56568d79dbd7699af805",
9
+ "index": "sha256:720469aca3cff3f1abe69374882d2c48399864be3778225e7754e94036e3be7a",
10
10
  "platforms": {
11
- "linux/arm64": "sha256:70dca2248666ee712ad5cb11fd013274ca4bb1efdafee732a0ec15492889f622",
12
- "linux/amd64": "sha256:a3377c70598ef4e1918a73feeebb0ec1b80b3cde956daac9b2b62f9d742b88dc"
11
+ "linux/arm64": "sha256:3aa68ad3736491de26c6ca9b52a49c80e6291228cc17a05caba4c060ea68913c",
12
+ "linux/amd64": "sha256:e77357a8c763244a5a5b4086fb771e81bec385526432ec6e77fb316f39158c53"
13
13
  }
14
14
  },
15
15
  "base": {
16
- "index": "sha256:86c6559bd51c10f8fc1ff6cbc0cf5386115fd7f0491a59f30f0d26a0203c200d",
16
+ "index": "sha256:a7c9342c50a493c990f8c26f1bec7e3919ad6010ce8a6cdfaa772487a1040989",
17
17
  "platforms": {
18
- "linux/amd64": "sha256:16056b4bd85ba1792791401003db0325c31d4aa4821ff40f6f2eb1e0fff1d3ce",
19
- "linux/arm64": "sha256:8d213f83ddd1ad9101b74b2b071f304ac8924ffbe68d79ece50668076e0172c0"
18
+ "linux/arm64": "sha256:c9152c3ff4854ba898df1b9fe89e8a94fd29aa5832e8cc5a4bd5fa2e06cee10f",
19
+ "linux/amd64": "sha256:817fc177f488b975bbbd196d9ec9d1d3effbf2c59d1ed82e979fcf5124c4c1aa"
20
20
  }
21
21
  },
22
22
  "web": {
23
- "index": "sha256:ffa089b83160e380e0b4447f483bf66cb87324f89b8e80b5776ed9346275a5ca",
23
+ "index": "sha256:143c2e79a950f732913726f32559f7c70323accf2727b34a12f332df91b765ef",
24
24
  "platforms": {
25
- "linux/arm64": "sha256:1baf14ee0f1a821c1562d12902fe362d3639f57acb31f969402f2a2d8486647f",
26
- "linux/amd64": "sha256:d3bd3aa785447f1679fdcb898921f614579d9eaad2aa9e828675ba7f82dc11ec"
25
+ "linux/arm64": "sha256:ebd0dbeee77a5fde4659b5f129713e5006cc205c629f837b56478e3691e85b9c",
26
+ "linux/amd64": "sha256:14429be7ee52afa0bd9c94248db3a84f90e74c29700a3f5f34da2989d7161431"
27
27
  }
28
28
  },
29
29
  "android": {
30
- "index": "sha256:830286886d8bb259e94e112e4f1bab5f153106365b17859d20c9ef714349e520",
30
+ "index": "sha256:249bdfda25dcd394c1e4955f3cd3e63140264697e9a543fbae1dce2ec3d80c38",
31
31
  "platforms": {
32
- "linux/amd64": "sha256:1004144243fea89a8915417954073e8ffabb20d8a9aed31045ce2a95c1abe1da"
32
+ "linux/amd64": "sha256:725375a79e64c93a7cc7e35f4708e36511f6a36212e0a3aaf44f6b5ec1057724"
33
+ }
34
+ },
35
+ "android-app": {
36
+ "index": "sha256:d739c6b72e1545b086f38fe5613b58f52877a36e14c2ffd763acdd0296802802",
37
+ "platforms": {
38
+ "linux/amd64": "sha256:a7124034f1ba3d888b3cd32c18051f87498c47ec515eac809b7440394c54ecb7"
33
39
  }
34
40
  },
35
41
  "linux": {
36
- "index": "sha256:8d4cc55d2ef8ea40845fd13708575e06f6aecdc035e7200deddf8c662d5c910f",
42
+ "index": "sha256:433af720cf95a99c4e007c0cfc98ab358c6ddc61fecca75a0b844f598d750b1b",
37
43
  "platforms": {
38
- "linux/arm64": "sha256:0de59cc6ce7b381f213af0d26ccc83e0c41545a91eb0b36c51832c7fb660566c",
39
- "linux/amd64": "sha256:3b3bc24d8f5dffe3a2408193265a807764fcf2744243c0a5e07f312f608fc6c0"
44
+ "linux/arm64": "sha256:0cf32948302c1a23294d28d20dd3b784790c7789b9e99bc8be56888bddb6aeb7",
45
+ "linux/amd64": "sha256:6da084ff433e792381aadd280b769aa1b09ba593e3e21ea4580f4736776e3cb9"
40
46
  }
41
47
  },
42
48
  "windows": {
43
- "index": "sha256:a31110874a9b6b9e3fec177edc8a8093905902bcc6abc6a85e45eb0927d4f070",
49
+ "index": "sha256:c1fb594cb245f6b0414f04cb7413881532438b204c7ce06f78f6deaea2d3cb24",
44
50
  "platforms": {
45
- "linux/arm64": "sha256:bd9ec6ba60952f929e09777374a3bb05512bbe796325c0e8a0b84e1a12d1b86c",
46
- "linux/amd64": "sha256:01f4bd8c4d1044bde68fe758d2632c510f8efb76aa4bad28696f9e9b199c8f4e"
51
+ "linux/amd64": "sha256:3ee3a4f9c565b0d2adedc3c699871bf8de4c2d7034b2b7a24309f4a6c4d0e64c",
52
+ "linux/arm64": "sha256:44702d741848f96d71dfb0a5322c37c9c248f7a38fe9e7c09b7d307ce000cc3f"
47
53
  }
48
54
  }
49
55
  }
@@ -0,0 +1,17 @@
1
+ # HTTP component runtime
2
+
3
+ What an http build (`crossbind build -p wasi -e http`) links besides the app: `handler.cpp`, the
4
+ `wasi:http/handler` export that calls the app's `crossbind::http::handle` (`include/crossbind/http.h`),
5
+ and `bindings/`, which `wit-bindgen c` generated from `wit/`.
6
+
7
+ `wit/deps/` holds the `http` package of the WASI 0.3.0 release, unchanged: `wasi-wit-0.3.0.tar.gz` from
8
+ https://github.com/WebAssembly/WASI/releases/tag/v0.3.0 (sha256
9
+ `596182ecd79311c8d010389b78b0253d54bee596254002df504ea5cf0124b894`), licensed as `wit/deps/LICENSE.md` says.
10
+
11
+ After changing `wit/`, regenerate the bindings with wit-bindgen 0.62.0; with `--check` it confirms instead
12
+ that the committed ones, the `.o` included, are what it generates:
13
+
14
+ ```bash
15
+ wit-bindgen c wit --world crossbind-http --out-dir bindings
16
+ wit-bindgen c wit --world crossbind-http --out-dir bindings --check
17
+ ```