crossbind 2.0.0-beta.56 → 2.0.0-beta.60

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.
@@ -14,7 +14,9 @@ const NUMBER_TYPES = new Set([
14
14
  'long long', 'unsigned int', 'unsigned long', 'unsigned short', 'unsigned long long',
15
15
  ]);
16
16
 
17
- function tsType(raw, classNames, { nullableSharedPtr = false } = {}) {
17
+ function tsType(raw, classNames, { isReturn = false } = {}) {
18
+ // A `const char *` crosses as a JS string, null when C++ returns NULL; other pointers stay native memory.
19
+ if (/^\s*(?:const\s+char|char\s+const)\s*\*\s*$/.test(raw)) return isReturn ? 'string | null' : 'string';
18
20
  let t = raw.trim().replace(/\bconst\b/g, '').replace(/&/g, '').trim().replace(/\s+/g, ' ');
19
21
  if (t.includes('*')) return null;
20
22
  const vector = t.match(/^std::vector<([\s\S]+)>$/);
@@ -26,7 +28,7 @@ function tsType(raw, classNames, { nullableSharedPtr = false } = {}) {
26
28
  if (shared) {
27
29
  if (!classNames.has(shared[1])) return null;
28
30
  // Embind shared_ptr returns can resolve to null; parameters take the plain object.
29
- return nullableSharedPtr ? `${shared[1]} | null` : shared[1];
31
+ return isReturn ? `${shared[1]} | null` : shared[1];
30
32
  }
31
33
  if (t === 'void') return 'void';
32
34
  if (t === 'bool') return 'boolean';
@@ -126,7 +128,8 @@ export function parseCppSurface(source, log = console.log) {
126
128
  : null;
127
129
  if (field) {
128
130
  const type = tsType(field[1], classNames);
129
- if (type !== null && FIELD_TYPES.has(type)) fields.push({ name: field[2], type });
131
+ // A reference member has no address a pointer to member could name, and a pointer member is memory.
132
+ if (type !== null && FIELD_TYPES.has(type) && !/[&*]/.test(field[1])) fields.push({ name: field[2], type });
130
133
  }
131
134
  continue;
132
135
  }
@@ -135,7 +138,7 @@ export function parseCppSurface(source, log = console.log) {
135
138
  if (args.includes(null)) { log(`crossbind: dts: skipped ${cls.name}::${name} (unsupported parameter type)`); continue; }
136
139
  if (name === cls.name && retRaw.trim() === '') { ctor = { args }; continue; }
137
140
  if (name.startsWith('~')) continue;
138
- const ret = tsType(retRaw, classNames, { nullableSharedPtr: true });
141
+ const ret = tsType(retRaw, classNames, { isReturn: true });
139
142
  if (ret === null) { log(`crossbind: dts: skipped ${cls.name}::${name} (unsupported return type '${retRaw.trim()}')`); continue; }
140
143
  methods.push({ name, isStatic: Boolean(staticKw), args, ret });
141
144
  }
@@ -0,0 +1,18 @@
1
+ import fs from 'node:fs';
2
+
3
+ // A bridge's .deps sidecar lists the bridges of the headers defining the types its declarations use. They link into the
4
+ // same module, since embind registers each class and enum once, in the bridge of the header that defines it.
5
+ export function withDependencyBridges(files) {
6
+ const listed = new Set(files);
7
+ const added = [];
8
+ for (const file of files) {
9
+ const sidecar = `${file}.deps`;
10
+ if (!fs.existsSync(sidecar)) continue;
11
+ for (const dependency of fs.readFileSync(sidecar, 'utf8').split('\n').filter(Boolean)) {
12
+ if (listed.has(dependency) || !fs.existsSync(dependency)) continue;
13
+ listed.add(dependency);
14
+ added.push(dependency);
15
+ }
16
+ }
17
+ return [...files, ...added];
18
+ }
@@ -6,15 +6,27 @@ import { Readable } from 'node:stream';
6
6
  import { pipeline } from 'node:stream/promises';
7
7
 
8
8
  export default async function downloadAndExtractFile(url, output, sha256) {
9
- if (fs.existsSync(`${output}/source`)) {
9
+ const archive = path.basename(url);
10
+ if (fs.existsSync(`${output}/source`) && sourceCameFrom(output, archive)) {
10
11
  return false;
11
12
  }
13
+ fs.rmSync(`${output}/source`, { recursive: true, force: true });
12
14
  const filePath = await downloadFile(url, output);
13
15
  verifyIntegrity(filePath, url, sha256);
14
16
  extractArchive(filePath, url, output);
17
+ fs.writeFileSync(`${output}/source.archive`, archive);
15
18
  return true;
16
19
  }
17
20
 
21
+ // A cached source tree only counts when it came from the archive the recipe names now, or a
22
+ // nativeVersion bump would keep compiling the old tree. Trees from before the marker are judged
23
+ // by the archive that was downloaded next to them.
24
+ function sourceCameFrom(output, archive) {
25
+ const marker = `${output}/source.archive`;
26
+ if (fs.existsSync(marker)) return fs.readFileSync(marker, 'utf8').trim() === archive;
27
+ return fs.existsSync(`${output}/${archive}`);
28
+ }
29
+
18
30
  // Extraction runs through the system tar (GNU tar and bsdtar both detect gzip/bzip2/xz, and
19
31
  // every platform the engine builds on ships one). Extracting into a scratch directory keeps
20
32
  // the archive from choosing where its files land, and gives the upstream root folder - which
@@ -89,7 +89,16 @@ export default function pullDockerImage(role = 'web', platform) {
89
89
  console.log('============= Downloading the docker image... =============');
90
90
  console.log('===========================================================');
91
91
  console.log('');
92
- execFileSync('docker', ['pull', ref], { stdio: 'inherit' });
92
+ try {
93
+ execFileSync('docker', ['pull', ref], { stdio: 'inherit' });
94
+ } catch (error) {
95
+ // Docker Desktop's Resource Saver stops the engine after a few idle minutes and answers
96
+ // `image inspect` from a cache with "No such image" meanwhile; the pull attempt has started
97
+ // the engine, so only a second lookup tells whether the image is really missing. A local-only
98
+ // tag (a dev image override) lands here too: its pull is denied, yet the image is present.
99
+ if (!isImagePresent(ref)) throw error;
100
+ console.log(`crossbind: ${ref} is present locally, so the failed pull is ignored.`);
101
+ }
93
102
  console.log('');
94
103
  console.log('===========================================================');
95
104
  console.log('');