@agoric/xsnap 0.14.3-other-dev-8f8782b.0 → 0.14.3-other-dev-fbe72e7.0.fbe72e7

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 (139) hide show
  1. package/README.md +6 -3
  2. package/api.js +4 -2
  3. package/build.env +1 -1
  4. package/moddable/modules/data/base64/base64.js +28 -0
  5. package/moddable/modules/data/base64/manifest.json +11 -0
  6. package/moddable/modules/data/base64/modBase64.c +188 -0
  7. package/moddable/modules/data/binaryMessage/BinaryMessage.js +106 -0
  8. package/moddable/modules/data/crc/crc.c +205 -0
  9. package/moddable/modules/data/crc/crc.js +36 -0
  10. package/moddable/modules/data/crc/manifest.json +8 -0
  11. package/moddable/modules/data/hex/hex.js +28 -0
  12. package/moddable/modules/data/hex/manifest.json +11 -0
  13. package/moddable/modules/data/hex/modHex.c +139 -0
  14. package/moddable/modules/data/logical/logical.js +32 -0
  15. package/moddable/modules/data/logical/modLogical.c +98 -0
  16. package/moddable/modules/data/qrcode/manifest.json +9 -0
  17. package/moddable/modules/data/qrcode/qrcode.c +93 -0
  18. package/moddable/modules/data/qrcode/qrcode.js +23 -0
  19. package/moddable/modules/data/qrcode/qrcodegen.c +1025 -0
  20. package/moddable/modules/data/qrcode/qrcodegen.h +267 -0
  21. package/moddable/modules/data/text/decoder/manifest.json +8 -0
  22. package/moddable/modules/data/text/decoder/textdecoder.c +480 -0
  23. package/moddable/modules/data/text/decoder/textdecoder.js +27 -0
  24. package/moddable/modules/data/text/encoder/manifest.json +8 -0
  25. package/moddable/modules/data/text/encoder/textencoder.c +232 -0
  26. package/moddable/modules/data/text/encoder/textencoder.js +24 -0
  27. package/moddable/modules/data/tinyint/tinyint.c +150 -0
  28. package/moddable/modules/data/tinyint/tinyint.js +53 -0
  29. package/moddable/modules/data/url/manifest.json +17 -0
  30. package/moddable/modules/data/url/url.c +1959 -0
  31. package/moddable/modules/data/url/url.js +210 -0
  32. package/moddable/modules/data/wavreader/manifest.json +8 -0
  33. package/moddable/modules/data/wavreader/wavreader.js +128 -0
  34. package/moddable/modules/data/zlib/deflate.c +161 -0
  35. package/moddable/modules/data/zlib/deflate.js +63 -0
  36. package/moddable/modules/data/zlib/inflate.c +145 -0
  37. package/moddable/modules/data/zlib/inflate.js +66 -0
  38. package/moddable/modules/data/zlib/manifest_deflate.json +9 -0
  39. package/moddable/modules/data/zlib/manifest_inflate.json +9 -0
  40. package/moddable/modules/data/zlib/miniz.c +4924 -0
  41. package/moddable/xs/includes/xs.d.ts +73 -0
  42. package/moddable/xs/includes/xs.h +1533 -0
  43. package/moddable/xs/includes/xsmc.h +206 -0
  44. package/moddable/xs/makefiles/lin/makefile +33 -0
  45. package/moddable/xs/makefiles/lin/xsc.mk +118 -0
  46. package/moddable/xs/makefiles/lin/xsid.mk +90 -0
  47. package/moddable/xs/makefiles/lin/xsl.mk +168 -0
  48. package/moddable/xs/makefiles/lin/xst.mk +201 -0
  49. package/moddable/xs/makefiles/mac/makefile +33 -0
  50. package/moddable/xs/makefiles/mac/xsc.mk +130 -0
  51. package/moddable/xs/makefiles/mac/xsid.mk +102 -0
  52. package/moddable/xs/makefiles/mac/xsl.mk +177 -0
  53. package/moddable/xs/makefiles/mac/xst.mk +203 -0
  54. package/moddable/xs/makefiles/mac/xst_no_asan.txt +52 -0
  55. package/moddable/xs/makefiles/win/build.bat +26 -0
  56. package/moddable/xs/makefiles/win/xsc.mak +142 -0
  57. package/moddable/xs/makefiles/win/xsid.mak +113 -0
  58. package/moddable/xs/makefiles/win/xsl.mak +186 -0
  59. package/moddable/xs/makefiles/win/xst.mak +195 -0
  60. package/moddable/xs/platforms/lin_xs.h +99 -0
  61. package/moddable/xs/platforms/mac_xs.h +97 -0
  62. package/moddable/xs/platforms/wasm_xs.h +79 -0
  63. package/moddable/xs/platforms/win_xs.h +104 -0
  64. package/moddable/xs/platforms/xsHost.h +63 -0
  65. package/moddable/xs/platforms/xsPlatform.h +618 -0
  66. package/moddable/xs/sources/xsAPI.c +2555 -0
  67. package/moddable/xs/sources/xsAll.c +294 -0
  68. package/moddable/xs/sources/xsAll.h +2741 -0
  69. package/moddable/xs/sources/xsArguments.c +222 -0
  70. package/moddable/xs/sources/xsArray.c +2657 -0
  71. package/moddable/xs/sources/xsAtomics.c +844 -0
  72. package/moddable/xs/sources/xsBigInt.c +1859 -0
  73. package/moddable/xs/sources/xsBoolean.c +109 -0
  74. package/moddable/xs/sources/xsCode.c +4493 -0
  75. package/moddable/xs/sources/xsCommon.c +1710 -0
  76. package/moddable/xs/sources/xsCommon.h +1142 -0
  77. package/moddable/xs/sources/xsDataView.c +2890 -0
  78. package/moddable/xs/sources/xsDate.c +1541 -0
  79. package/moddable/xs/sources/xsDebug.c +2710 -0
  80. package/moddable/xs/sources/xsDefaults.c +134 -0
  81. package/moddable/xs/sources/xsError.c +353 -0
  82. package/moddable/xs/sources/xsFunction.c +776 -0
  83. package/moddable/xs/sources/xsGenerator.c +865 -0
  84. package/moddable/xs/sources/xsGlobal.c +839 -0
  85. package/moddable/xs/sources/xsJSON.c +1091 -0
  86. package/moddable/xs/sources/xsLexical.c +1969 -0
  87. package/moddable/xs/sources/xsLockdown.c +933 -0
  88. package/moddable/xs/sources/xsMapSet.c +1649 -0
  89. package/moddable/xs/sources/xsMarshall.c +1020 -0
  90. package/moddable/xs/sources/xsMath.c +624 -0
  91. package/moddable/xs/sources/xsMemory.c +1941 -0
  92. package/moddable/xs/sources/xsModule.c +3101 -0
  93. package/moddable/xs/sources/xsNumber.c +560 -0
  94. package/moddable/xs/sources/xsObject.c +1102 -0
  95. package/moddable/xs/sources/xsPlatforms.c +480 -0
  96. package/moddable/xs/sources/xsProfile.c +577 -0
  97. package/moddable/xs/sources/xsPromise.c +1199 -0
  98. package/moddable/xs/sources/xsProperty.c +636 -0
  99. package/moddable/xs/sources/xsProxy.c +1014 -0
  100. package/moddable/xs/sources/xsRegExp.c +1168 -0
  101. package/moddable/xs/sources/xsRun.c +4889 -0
  102. package/moddable/xs/sources/xsScope.c +1293 -0
  103. package/moddable/xs/sources/xsScript.c +288 -0
  104. package/moddable/xs/sources/xsScript.h +1186 -0
  105. package/moddable/xs/sources/xsSnapshot.c +2161 -0
  106. package/moddable/xs/sources/xsSnapshot.h +51 -0
  107. package/moddable/xs/sources/xsSourceMap.c +218 -0
  108. package/moddable/xs/sources/xsString.c +3332 -0
  109. package/moddable/xs/sources/xsSymbol.c +503 -0
  110. package/moddable/xs/sources/xsSyntaxical.c +4193 -0
  111. package/moddable/xs/sources/xsTree.c +1893 -0
  112. package/moddable/xs/sources/xsType.c +1488 -0
  113. package/moddable/xs/sources/xsdtoa.c +6672 -0
  114. package/moddable/xs/sources/xsmc.c +340 -0
  115. package/moddable/xs/sources/xsre.c +7578 -0
  116. package/package.json +44 -24
  117. package/scripts/get_xsnap_version.sh +14 -0
  118. package/scripts/test-package.sh +21 -0
  119. package/src/avaAssertXS.js +6 -2
  120. package/src/avaHandler.cjs +2 -5
  121. package/src/avaXS.js +14 -12
  122. package/src/build.js +258 -133
  123. package/src/globals.d.ts +2 -2
  124. package/src/replay.js +12 -8
  125. package/src/xsnap.js +131 -115
  126. package/src/xsrepl.js +8 -9
  127. package/xsnap-native/xsnap/makefiles/lin/makefile +10 -0
  128. package/xsnap-native/xsnap/makefiles/lin/xsnap-worker.mk +156 -0
  129. package/xsnap-native/xsnap/makefiles/lin/xsnap.mk +144 -0
  130. package/xsnap-native/xsnap/makefiles/mac/makefile +10 -0
  131. package/xsnap-native/xsnap/makefiles/mac/xsnap-worker.mk +165 -0
  132. package/xsnap-native/xsnap/makefiles/mac/xsnap.mk +153 -0
  133. package/xsnap-native/xsnap/sources/xsnap-worker.c +1024 -0
  134. package/xsnap-native/xsnap/sources/xsnap.c +717 -0
  135. package/xsnap-native/xsnap/sources/xsnap.h +142 -0
  136. package/xsnap-native/xsnap/sources/xsnapPlatform.c +1501 -0
  137. package/xsnap-native/xsnap/sources/xsnapPlatform.h +105 -0
  138. package/CHANGELOG.md +0 -622
  139. package/src/defer.js +0 -31
package/src/build.js CHANGED
@@ -1,18 +1,27 @@
1
1
  #!/usr/bin/env node
2
- /* global process */
3
- /* eslint-disable @jessie.js/no-nested-await -- test/build code */
2
+ /* eslint-env node */
4
3
  import * as childProcessTop from 'child_process';
4
+ import { fileURLToPath } from 'url';
5
5
  import fsTop from 'fs';
6
6
  import osTop from 'os';
7
7
 
8
8
  const { freeze } = Object;
9
9
 
10
10
  /** @param {string} path */
11
- const asset = path => new URL(path, import.meta.url).pathname;
11
+ const asset = path => fileURLToPath(new URL(path, import.meta.url));
12
+
13
+ /** @param {Promise<unknown>} p */
14
+ const isRejected = p =>
15
+ p.then(
16
+ () => false,
17
+ () => true,
18
+ );
19
+
20
+ /** @typedef {{ path: string, make?: string }} ModdablePlatform */
12
21
 
13
22
  const ModdableSDK = {
14
23
  MODDABLE: asset('../moddable'),
15
- /** @type { Record<string, { path: string, make?: string }>} */
24
+ /** @type { Record<string, ModdablePlatform>} */
16
25
  platforms: {
17
26
  Linux: { path: 'lin' },
18
27
  Darwin: { path: 'mac' },
@@ -22,7 +31,8 @@ const ModdableSDK = {
22
31
  };
23
32
 
24
33
  /**
25
- * Adapt spawn to Promises style.
34
+ * Create promise-returning functions for asynchronous execution of no-input
35
+ * commands.
26
36
  *
27
37
  * @param {string} command
28
38
  * @param {{
@@ -48,6 +58,8 @@ function makeCLI(command, { spawn }) {
48
58
 
49
59
  return freeze({
50
60
  /**
61
+ * Run the command, writing directly to stdout and stderr.
62
+ *
51
63
  * @param {string[]} args
52
64
  * @param {{ cwd?: string }} [opts]
53
65
  */
@@ -55,26 +67,30 @@ function makeCLI(command, { spawn }) {
55
67
  const { cwd = '.' } = opts || {};
56
68
  const child = spawn(command, args, {
57
69
  cwd,
58
- stdio: ['inherit', 'inherit', 'inherit'],
70
+ stdio: ['ignore', 'inherit', 'inherit'],
59
71
  });
60
72
  return wait(child);
61
73
  },
62
74
  /**
75
+ * Run the command, writing directly to stderr but capturing and returning
76
+ * stdout.
77
+ *
63
78
  * @param {string[]} args
64
- * @param {{ cwd?: string }} [opts]
79
+ * @param {{ cwd?: string, fullOutput?: boolean }} [opts]
80
+ * @returns {Promise<string>} command output, stripped of trailing
81
+ * whitespace unless option "fullOutput" is true
65
82
  */
66
- pipe: (args, opts) => {
67
- const { cwd = '.' } = opts || {};
83
+ pipe: async (args, opts) => {
84
+ const { cwd = '.', fullOutput = false } = opts || {};
68
85
  const child = spawn(command, args, {
69
86
  cwd,
70
- stdio: ['inherit', 'pipe', 'inherit'],
87
+ stdio: ['ignore', 'pipe', 'inherit'],
71
88
  });
72
- let output = '';
73
- child.stdout.setEncoding('utf8');
74
- child.stdout.on('data', data => {
75
- output += data.toString();
76
- });
77
- return wait(child).then(() => output);
89
+ const chunks = [];
90
+ child.stdout.on('data', chunk => chunks.push(chunk));
91
+ await wait(child);
92
+ const output = Buffer.concat(chunks).toString('utf8');
93
+ return fullOutput ? output : output.trimEnd();
78
94
  },
79
95
  });
80
96
  }
@@ -85,28 +101,6 @@ function makeCLI(command, { spawn }) {
85
101
  * @param {{ git: ReturnType<typeof makeCLI> }} io
86
102
  */
87
103
  const makeSubmodule = (path, repoUrl, { git }) => {
88
- /** @param {string} text */
89
- const parseStatus = text =>
90
- text
91
- .split('\n')
92
- // From `git submodule --help`:
93
- // Show the status of the submodules. This will print the SHA-1 of the
94
- // currently checked out commit for each submodule, along with the
95
- // submodule path and the output of git describe for the SHA-1. Each
96
- // SHA-1 will possibly be prefixed with - if the submodule is not
97
- // initialized, + if the currently checked out submodule commit does
98
- // not match the SHA-1 found in the index of the containing repository
99
- // and U if the submodule has merge conflicts.
100
- //
101
- // We discovered that in other cases, the prefix is a single space.
102
- .map(line => [line[0], ...line.slice(1).split(' ', 3)])
103
- .map(([prefix, hash, statusPath, describe]) => ({
104
- prefix,
105
- hash,
106
- path: statusPath,
107
- describe,
108
- }));
109
-
110
104
  return freeze({
111
105
  path,
112
106
  clone: async () => git.run(['clone', repoUrl, path]),
@@ -114,93 +108,107 @@ const makeSubmodule = (path, repoUrl, { git }) => {
114
108
  checkout: async commitHash =>
115
109
  git.run(['checkout', commitHash], { cwd: path }),
116
110
  init: async () => git.run(['submodule', 'update', '--init', '--checkout']),
117
- status: async () =>
118
- git.pipe(['submodule', 'status', path]).then(parseStatus),
119
- /** @param {string} leaf */
111
+ status: async () => {
112
+ const line = await git.pipe(['submodule', 'status', path]);
113
+ // From `git submodule --help`:
114
+ // status [--cached] [--recursive] [--] [<path>...]
115
+ // Show the status of the submodules. This will print the SHA-1 of the
116
+ // currently checked out commit for each submodule, along with the
117
+ // submodule path and the output of git describe for the SHA-1. Each
118
+ // SHA-1 will possibly be prefixed with - if the submodule is not
119
+ // initialized, + if the currently checked out submodule commit does
120
+ // not match the SHA-1 found in the index of the containing repository
121
+ // and U if the submodule has merge conflicts.
122
+ //
123
+ // We discovered that in other cases, the prefix is a single space.
124
+ const prefix = line[0];
125
+ const [hash, statusPath, ...describe] = line.slice(1).split(' ');
126
+ return {
127
+ prefix,
128
+ hash,
129
+ path: statusPath,
130
+ describe: describe.join(' '),
131
+ };
132
+ },
133
+ /**
134
+ * Read a specific configuration value for this submodule (e.g., "path" or
135
+ * "url") from the top-level .gitmodules.
136
+ *
137
+ * @param {string} leaf
138
+ */
120
139
  config: async leaf => {
121
140
  // git rev-parse --show-toplevel
122
- const top = await git
123
- .pipe(['rev-parse', '--show-toplevel'])
124
- .then(l => l.trimEnd());
125
- // assume full paths
126
- const name = path.slice(top.length + 1);
127
- // git config -f ../../.gitmodules --get submodule."$name".url
128
- const value = await git
129
- .pipe([
130
- 'config',
131
- '-f',
132
- `${top}/.gitmodules`,
133
- '--get',
134
- `submodule.${name}.${leaf}`,
135
- ])
136
- .then(l => l.trimEnd());
141
+ const repoRoot = await git.pipe(['rev-parse', '--show-toplevel']);
142
+ if (!path.startsWith(`${repoRoot}/`)) {
143
+ throw Error(
144
+ `Expected submodule path ${path} to be a subdirectory of repository ${repoRoot}`,
145
+ );
146
+ }
147
+ const relativePath = path.slice(repoRoot.length + 1);
148
+ // git config -f ../../.gitmodules --get submodule.${relativePath}.${leaf}
149
+ const value = await git.pipe([
150
+ 'config',
151
+ '-f',
152
+ `${repoRoot}/.gitmodules`,
153
+ '--get',
154
+ `submodule.${relativePath}.${leaf}`,
155
+ ]);
137
156
  return value;
138
157
  },
139
158
  });
140
159
  };
141
160
 
142
161
  /**
143
- * @param {string[]} args
162
+ * @typedef {{
163
+ * url: string,
164
+ * path: string,
165
+ * commitHash?: string,
166
+ * envPrefix: string,
167
+ * }} SubmoduleDescriptor
168
+ */
169
+
170
+ /**
171
+ * @param {SubmoduleDescriptor[]} submodules
144
172
  * @param {{
145
- * env: Record<string, string | undefined>,
173
+ * git: ReturnType<typeof makeCLI>,
146
174
  * stdout: typeof process.stdout,
147
- * spawn: typeof import('child_process').spawn,
148
- * fs: {
149
- * existsSync: typeof import('fs').existsSync,
150
- * rmdirSync: typeof import('fs').rmdirSync,
151
- * readFile: typeof import('fs').promises.readFile,
152
- * },
153
- * os: {
154
- * type: typeof import('os').type,
155
- * }
156
175
  * }} io
157
176
  */
158
- async function main(args, { env, stdout, spawn, fs, os }) {
159
- const git = makeCLI('git', { spawn });
160
-
161
- // When changing/adding entries here, make sure to search the whole project
162
- // for `@@AGORIC_DOCKER_SUBMODULES@@`
163
- const submodules = [
164
- {
165
- url: env.MODDABLE_URL || 'https://github.com/agoric-labs/moddable.git',
166
- path: ModdableSDK.MODDABLE,
167
- commitHash: env.MODDABLE_COMMIT_HASH,
168
- envPrefix: 'MODDABLE_',
169
- },
170
- {
171
- url:
172
- env.XSNAP_NATIVE_URL || 'https://github.com/agoric-labs/xsnap-pub.git',
173
- path: asset('../xsnap-native'),
174
- commitHash: env.XSNAP_NATIVE_COMMIT_HASH,
175
- envPrefix: 'XSNAP_NATIVE_',
176
- },
177
- ];
178
-
179
- if (args.includes('--show-env')) {
180
- for (const submodule of submodules) {
181
- const { path, envPrefix, commitHash } = submodule;
182
- if (!commitHash) {
183
- // We need to glean the commitHash and url from Git.
184
- const sm = makeSubmodule(path, '?', { git });
185
- // eslint-disable-next-line no-await-in-loop
186
- const [[{ hash }], url] = await Promise.all([
187
- sm.status(),
188
- sm.config('url'),
189
- ]);
190
- submodule.commitHash = hash;
191
- submodule.url = url;
192
- }
193
- stdout.write(`${envPrefix}URL=${submodule.url}\n`);
194
- stdout.write(`${envPrefix}COMMIT_HASH=${submodule.commitHash}\n`);
177
+ const showEnv = async (submodules, { git, stdout }) => {
178
+ await null;
179
+ for (const desc of submodules) {
180
+ const { path, envPrefix } = desc;
181
+ let { url, commitHash } = desc;
182
+ if (!commitHash) {
183
+ // We need to glean the commitHash and url from Git.
184
+ const submodule = makeSubmodule(path, '?', { git });
185
+ const [{ hash }, gitUrl] = await Promise.all([
186
+ submodule.status(),
187
+ submodule.config('url'),
188
+ ]);
189
+ commitHash = hash;
190
+ url = gitUrl;
195
191
  }
196
- return;
192
+ stdout.write(`${envPrefix}URL=${url}\n`);
193
+ stdout.write(`${envPrefix}COMMIT_HASH=${commitHash}\n`);
197
194
  }
195
+ };
198
196
 
197
+ /**
198
+ * @param {SubmoduleDescriptor[]} submodules
199
+ * @param {{
200
+ * fs: Pick<typeof import('fs'), 'existsSync' | 'rmdirSync'>,
201
+ * git: ReturnType<typeof makeCLI>,
202
+ * }} io
203
+ */
204
+ const updateSubmodules = async (submodules, { fs, git }) => {
205
+ await null;
199
206
  for (const { url, path, commitHash } of submodules) {
200
207
  const submodule = makeSubmodule(path, url, { git });
201
208
 
202
- // Allow overriding of the checked-out version of the submodule.
203
- if (commitHash) {
209
+ if (!commitHash) {
210
+ await submodule.init();
211
+ } else {
204
212
  // Do the moral equivalent of submodule update when explicitly overriding.
205
213
  try {
206
214
  fs.rmdirSync(submodule.path);
@@ -208,34 +216,50 @@ async function main(args, { env, stdout, spawn, fs, os }) {
208
216
  // ignore
209
217
  }
210
218
  if (!fs.existsSync(submodule.path)) {
211
- // eslint-disable-next-line no-await-in-loop
212
219
  await submodule.clone();
213
220
  }
214
- // eslint-disable-next-line no-await-in-loop
215
221
  await submodule.checkout(commitHash);
216
- } else {
217
- // eslint-disable-next-line no-await-in-loop
218
- await submodule.init();
219
222
  }
220
223
  }
224
+ };
221
225
 
226
+ /**
227
+ * @param {ModdablePlatform} platform
228
+ * @param {boolean} force
229
+ * @param {{
230
+ * fs: Pick<typeof import('fs'), 'existsSync'> &
231
+ * Pick<typeof import('fs').promises, 'readFile' | 'writeFile'>,
232
+ * make: ReturnType<typeof makeCLI>,
233
+ * }} io
234
+ */
235
+ const buildXsnap = async (platform, force, { fs, make }) => {
222
236
  const pjson = await fs.readFile(asset('../package.json'), 'utf-8');
223
237
  const pkg = JSON.parse(pjson);
224
238
 
225
- const platform = ModdableSDK.platforms[os.type()];
226
- if (!platform) {
227
- throw Error(`Unsupported OS found: ${os.type()}`);
239
+ const configEnvs = [
240
+ `XSNAP_VERSION=${pkg.version}`,
241
+ `CC=cc "-D__has_builtin(x)=1"`,
242
+ ];
243
+
244
+ const configEnvFile = asset('../build.config.env');
245
+ const existingConfigEnvs = fs.existsSync(configEnvFile)
246
+ ? await fs.readFile(configEnvFile, 'utf-8')
247
+ : '';
248
+
249
+ const expectedConfigEnvs = configEnvs.concat('').join('\n');
250
+ if (force || existingConfigEnvs.trim() !== expectedConfigEnvs.trim()) {
251
+ await fs.writeFile(configEnvFile, expectedConfigEnvs);
228
252
  }
229
253
 
230
- const make = makeCLI(platform.make || 'make', { spawn });
231
254
  for (const goal of ModdableSDK.buildGoals) {
232
- // eslint-disable-next-line no-await-in-loop
233
255
  await make.run(
234
256
  [
235
257
  `MODDABLE=${ModdableSDK.MODDABLE}`,
236
258
  `GOAL=${goal}`,
237
- `XSNAP_VERSION=${pkg.version}`,
238
- `CC=cc "-D__has_builtin(x)=1"`,
259
+ // Any other configuration variables that affect the build output
260
+ // should be placed in `configEnvs` to force a rebuild if they change
261
+ ...configEnvs,
262
+ `EXTRA_DEPS=${configEnvFile}`,
239
263
  '-f',
240
264
  'xsnap-worker.mk',
241
265
  ],
@@ -244,21 +268,122 @@ async function main(args, { env, stdout, spawn, fs, os }) {
244
268
  },
245
269
  );
246
270
  }
271
+ };
272
+
273
+ /**
274
+ * @param {string[]} args
275
+ * @param {{
276
+ * env: Record<string, string | undefined>,
277
+ * stdout: typeof process.stdout,
278
+ * spawn: typeof import('child_process').spawn,
279
+ * fs: Pick<typeof import('fs'), 'existsSync' | 'rmdirSync'> &
280
+ * Pick<typeof import('fs').promises, 'readFile' | 'writeFile'>,
281
+ * os: Pick<typeof import('os'), 'type'>,
282
+ * }} io
283
+ */
284
+ async function main(args, { env, stdout, spawn, fs, os }) {
285
+ // I solemnly swear I will do no synchronous work followed by a variable
286
+ // number turns of the event loop.
287
+ await null;
288
+
289
+ const osType = os.type();
290
+ const platform = ModdableSDK.platforms[osType];
291
+ if (!platform) {
292
+ throw Error(`xsnap does not support OS ${osType}`);
293
+ }
294
+
295
+ const git = makeCLI('git', { spawn });
296
+ const make = makeCLI(platform.make || 'make', { spawn });
297
+
298
+ // When changing/adding entries here, make sure to search the whole project
299
+ // for `@@AGORIC_DOCKER_SUBMODULES@@`
300
+ const submodules = [
301
+ {
302
+ url: env.MODDABLE_URL || 'https://github.com/agoric-labs/moddable.git',
303
+ path: ModdableSDK.MODDABLE,
304
+ commitHash: env.MODDABLE_COMMIT_HASH,
305
+ envPrefix: 'MODDABLE_',
306
+ },
307
+ {
308
+ url:
309
+ env.XSNAP_NATIVE_URL || 'https://github.com/agoric-labs/xsnap-pub.git',
310
+ path: asset('../xsnap-native'),
311
+ commitHash: env.XSNAP_NATIVE_COMMIT_HASH,
312
+ envPrefix: 'XSNAP_NATIVE_',
313
+ },
314
+ ];
315
+
316
+ // We build both release and debug executables, so checking for only the
317
+ // former is fine.
318
+ // XXX This will need to account for the .exe extension if we recover support
319
+ // for Windows.
320
+ const bin = asset(
321
+ `../xsnap-native/xsnap/build/bin/${platform.path}/release/xsnap-worker`,
322
+ );
323
+ const hasBin = fs.existsSync(bin);
324
+ const hasSource = fs.existsSync(asset('../moddable/xs/includes/xs.h'));
325
+ const hasGit = fs.existsSync(asset('../moddable/.git'));
326
+
327
+ // If a git submodule is present or source files and prebuilt executables are
328
+ // both absent, consider ourselves to be in an active git checkout (as opposed
329
+ // to e.g. an extracted npm tarball).
330
+ const isWorkingCopy = hasGit || (!hasSource && !hasBin);
331
+
332
+ // --show-env reports submodule status without making changes.
333
+ if (args.includes('--show-env')) {
334
+ if (!isWorkingCopy) {
335
+ throw Error('XSnap requires a working copy and git to --show-env');
336
+ }
337
+ await showEnv(submodules, { git, stdout });
338
+ return;
339
+ }
340
+
341
+ // Fetch/update source files via `git submodule` as appropriate.
342
+ if (isWorkingCopy) {
343
+ await updateSubmodules(submodules, { fs, git });
344
+ }
345
+
346
+ // If we now have source files, (re)build from them.
347
+ // Otherwise, require presence of a previously-built executable.
348
+ if (hasSource || isWorkingCopy) {
349
+ // Force a rebuild if for some reason the binary is out of date
350
+ // since the make checks may not always detect that situation.
351
+ const npm = makeCLI('npm', { spawn });
352
+ const force = await (!hasBin ||
353
+ isRejected(
354
+ npm.run(['run', '-s', 'check-version'], { cwd: asset('..') }),
355
+ ));
356
+ await buildXsnap(platform, force, { fs, make });
357
+ } else if (!hasBin) {
358
+ throw Error(
359
+ 'XSnap has neither sources nor a pre-built binary. Docker? .dockerignore? npm files?',
360
+ );
361
+ }
247
362
  }
248
363
 
249
- main(process.argv.slice(2), {
250
- env: { ...process.env },
251
- stdout: process.stdout,
252
- spawn: childProcessTop.spawn,
253
- fs: {
254
- readFile: fsTop.promises.readFile,
255
- existsSync: fsTop.existsSync,
256
- rmdirSync: fsTop.rmdirSync,
364
+ const run = () =>
365
+ main(process.argv.slice(2), {
366
+ env: { ...process.env },
367
+ stdout: process.stdout,
368
+ spawn: childProcessTop.spawn,
369
+ fs: {
370
+ existsSync: fsTop.existsSync,
371
+ rmdirSync: fsTop.rmdirSync,
372
+ readFile: fsTop.promises.readFile,
373
+ writeFile: fsTop.promises.writeFile,
374
+ },
375
+ os: {
376
+ type: osTop.type,
377
+ },
378
+ });
379
+
380
+ process.exitCode = 1;
381
+ run().then(
382
+ () => {
383
+ process.exitCode = 0;
257
384
  },
258
- os: {
259
- type: osTop.type,
385
+ err => {
386
+ console.error('Failed with', err);
387
+ process.exit(process.exitCode || 1);
260
388
  },
261
- }).catch(e => {
262
- console.error(e);
263
- process.exit(1);
264
- });
389
+ );
package/src/globals.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- declare var issueCommand: (msg: ArrayBuffer) => ArrayBuffer;
1
+ declare var issueCommand: (msg: ArrayBufferLike) => ArrayBuffer;
2
2
 
3
3
  namespace global {
4
- declare var issueCommand: (msg: ArrayBuffer) => ArrayBuffer;
4
+ declare var issueCommand: (msg: ArrayBufferLike) => ArrayBuffer;
5
5
  }
package/src/replay.js CHANGED
@@ -13,6 +13,7 @@ import osPowers from 'os';
13
13
  import fsPowers from 'fs';
14
14
  import { Readable } from 'stream';
15
15
  import { tmpName as tmpNamePower } from 'tmp';
16
+ import { fileURLToPath } from 'url';
16
17
  import { makeQueue } from '@endo/stream';
17
18
  import { xsnap, DEFAULT_CRANK_METERING_LIMIT } from './xsnap.js';
18
19
 
@@ -38,7 +39,9 @@ function makeSyncStorage(path, { writeFileSync }) {
38
39
  file: fn => {
39
40
  /** @param {Uint8Array} data */
40
41
  const put = data =>
41
- writeFileSync(new URL(fn, base).pathname, data, { flag: 'wx' });
42
+ writeFileSync(fileURLToPath(new URL(fn, base)), data, {
43
+ flag: 'wx',
44
+ });
42
45
 
43
46
  return freeze({
44
47
  put,
@@ -60,14 +63,18 @@ function makeSyncAccess(path, { readdirSync, readFileSync }) {
60
63
  const base = new URL(path, 'file://');
61
64
  /** @param {string} fn */
62
65
  const file = fn => {
63
- const fullname = new URL(fn, base).pathname;
66
+ const fullname = fileURLToPath(new URL(fn, base));
64
67
 
65
68
  return freeze({
66
69
  getData: () => readFileSync(fullname),
67
70
  getText: () => readFileSync(fullname, 'utf-8'),
68
71
  });
69
72
  };
70
- return freeze({ path, file, readdir: () => readdirSync(base.pathname) });
73
+ return freeze({
74
+ path,
75
+ file,
76
+ readdir: () => readdirSync(fileURLToPath(base)),
77
+ });
71
78
  }
72
79
 
73
80
  /**
@@ -227,14 +234,12 @@ export async function replayXSnap(
227
234
  const seq = parseInt(digits, 10);
228
235
  console.log(folder, seq, kind);
229
236
  if (running && !['command', 'reply'].includes(kind)) {
230
- // eslint-disable-next-line @jessie.js/no-nested-await
231
237
  await running;
232
238
  running = undefined;
233
239
  }
234
240
  const file = rd.file(step);
235
241
  switch (kind) {
236
242
  case 'isReady':
237
- // eslint-disable-next-line @jessie.js/no-nested-await
238
243
  await it.isReady();
239
244
  break;
240
245
  case 'evaluate':
@@ -254,7 +259,6 @@ export async function replayXSnap(
254
259
  console.log(folder, step, 'ignoring remaining steps from', folder);
255
260
  return;
256
261
  } else {
257
- // eslint-disable-next-line @jessie.js/no-nested-await
258
262
  await (async () => {
259
263
  const snapshotPath = file.getText();
260
264
  const snapFile = await opts.fs.open(snapshotPath, 'w');
@@ -322,8 +326,8 @@ export async function main(
322
326
  await replayXSnap(options, folders, { readdirSync, readFileSync });
323
327
  }
324
328
 
325
- /* global process */
326
- if (process.argv[1] === new URL(import.meta.url).pathname) {
329
+ /* eslint-env node */
330
+ if (process.argv[1] === fileURLToPath(new URL(import.meta.url))) {
327
331
  main([...process.argv.slice(2)], {
328
332
  spawn: childProcessPowers.spawn,
329
333
  fs: { ...fsPowers, ...fsPowers.promises },