vitest-pool-assemblyscript 0.2.0

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 (83) hide show
  1. package/BINARYEN_VERSION +1 -0
  2. package/LICENSE +53 -0
  3. package/README.md +607 -0
  4. package/assembly/compare.ts +219 -0
  5. package/assembly/describe.ts +104 -0
  6. package/assembly/expect.ts +335 -0
  7. package/assembly/index.ts +14 -0
  8. package/assembly/options.ts +198 -0
  9. package/assembly/test.ts +147 -0
  10. package/assembly/tsconfig.json +6 -0
  11. package/binding.gyp +62 -0
  12. package/dist/ast-visitor-DC3SuTzs.mjs +310 -0
  13. package/dist/ast-visitor-DC3SuTzs.mjs.map +1 -0
  14. package/dist/compile-runner-8h0dBwG2.mjs +80 -0
  15. package/dist/compile-runner-8h0dBwG2.mjs.map +1 -0
  16. package/dist/compiler/transforms/strip-inline.d.mts +18 -0
  17. package/dist/compiler/transforms/strip-inline.d.mts.map +1 -0
  18. package/dist/compiler/transforms/strip-inline.mjs +38 -0
  19. package/dist/compiler/transforms/strip-inline.mjs.map +1 -0
  20. package/dist/compiler-CN6BRK_N.mjs +295 -0
  21. package/dist/compiler-CN6BRK_N.mjs.map +1 -0
  22. package/dist/config/index-v3.d.mts +111 -0
  23. package/dist/config/index-v3.d.mts.map +1 -0
  24. package/dist/config/index-v3.mjs +11 -0
  25. package/dist/config/index-v3.mjs.map +1 -0
  26. package/dist/config/index.d.mts +4 -0
  27. package/dist/config/index.mjs +8 -0
  28. package/dist/constants-CA50WBdr.mjs +130 -0
  29. package/dist/constants-CA50WBdr.mjs.map +1 -0
  30. package/dist/coverage-merge-0WqdC-dq.mjs +22 -0
  31. package/dist/coverage-merge-0WqdC-dq.mjs.map +1 -0
  32. package/dist/coverage-provider/index.d.mts +15 -0
  33. package/dist/coverage-provider/index.d.mts.map +1 -0
  34. package/dist/coverage-provider/index.mjs +535 -0
  35. package/dist/coverage-provider/index.mjs.map +1 -0
  36. package/dist/custom-provider-options-CF5C1kXb.d.mts +26 -0
  37. package/dist/custom-provider-options-CF5C1kXb.d.mts.map +1 -0
  38. package/dist/debug-IeEHsxy0.mjs +195 -0
  39. package/dist/debug-IeEHsxy0.mjs.map +1 -0
  40. package/dist/index-internal.d.mts +23 -0
  41. package/dist/index-internal.d.mts.map +1 -0
  42. package/dist/index-internal.mjs +4 -0
  43. package/dist/index-v3.d.mts +7 -0
  44. package/dist/index-v3.d.mts.map +1 -0
  45. package/dist/index-v3.mjs +206 -0
  46. package/dist/index-v3.mjs.map +1 -0
  47. package/dist/index.d.mts +3 -0
  48. package/dist/index.mjs +8 -0
  49. package/dist/load-user-imports-J9eaAW0_.mjs +801 -0
  50. package/dist/load-user-imports-J9eaAW0_.mjs.map +1 -0
  51. package/dist/pool-runner-init-CEwLyNI3.d.mts +8 -0
  52. package/dist/pool-runner-init-CEwLyNI3.d.mts.map +1 -0
  53. package/dist/pool-runner-init-d5qScS41.mjs +400 -0
  54. package/dist/pool-runner-init-d5qScS41.mjs.map +1 -0
  55. package/dist/pool-thread/compile-worker-thread.d.mts +7 -0
  56. package/dist/pool-thread/compile-worker-thread.d.mts.map +1 -0
  57. package/dist/pool-thread/compile-worker-thread.mjs +42 -0
  58. package/dist/pool-thread/compile-worker-thread.mjs.map +1 -0
  59. package/dist/pool-thread/test-worker-thread.d.mts +7 -0
  60. package/dist/pool-thread/test-worker-thread.d.mts.map +1 -0
  61. package/dist/pool-thread/test-worker-thread.mjs +39 -0
  62. package/dist/pool-thread/test-worker-thread.mjs.map +1 -0
  63. package/dist/pool-thread/v3-tinypool-thread.d.mts +7 -0
  64. package/dist/pool-thread/v3-tinypool-thread.d.mts.map +1 -0
  65. package/dist/pool-thread/v3-tinypool-thread.mjs +57 -0
  66. package/dist/pool-thread/v3-tinypool-thread.mjs.map +1 -0
  67. package/dist/resolve-config-as1w-Qyz.mjs +65 -0
  68. package/dist/resolve-config-as1w-Qyz.mjs.map +1 -0
  69. package/dist/test-runner-B2BpyPNK.mjs +142 -0
  70. package/dist/test-runner-B2BpyPNK.mjs.map +1 -0
  71. package/dist/types-8KKo9Hbf.d.mts +228 -0
  72. package/dist/types-8KKo9Hbf.d.mts.map +1 -0
  73. package/dist/vitest-file-tasks-BUwzh375.mjs +61 -0
  74. package/dist/vitest-file-tasks-BUwzh375.mjs.map +1 -0
  75. package/dist/vitest-tasks-BKS7689f.mjs +319 -0
  76. package/dist/vitest-tasks-BKS7689f.mjs.map +1 -0
  77. package/dist/worker-rpc-channel-lbhK7Qz8.mjs +25 -0
  78. package/dist/worker-rpc-channel-lbhK7Qz8.mjs.map +1 -0
  79. package/package.json +112 -0
  80. package/prebuilds/linux-x64/vitest-pool-assemblyscript.glibc.node +0 -0
  81. package/scripts/install.js +91 -0
  82. package/scripts/setup-binaryen.js +179 -0
  83. package/src/native-instrumentation/addon.cpp +788 -0
@@ -0,0 +1,25 @@
1
+ import { MessageChannel } from "node:worker_threads";
2
+ import { createBirpc } from "birpc";
3
+ import { createMethodsRPC } from "vitest/node";
4
+
5
+ //#region src/pool/worker-rpc-channel.ts
6
+ /**
7
+ * Create a MessageChannel with RPC for worker thread communication
8
+ */
9
+ function createWorkerRPCChannel(project, collect) {
10
+ const channel = new MessageChannel();
11
+ const workerPort = channel.port1;
12
+ const poolPort = channel.port2;
13
+ return {
14
+ workerPort,
15
+ poolPort,
16
+ rpc: createBirpc(createMethodsRPC(project, { collect }), {
17
+ post: (v) => poolPort.postMessage(v),
18
+ on: (fn) => poolPort.on("message", fn)
19
+ })
20
+ };
21
+ }
22
+
23
+ //#endregion
24
+ export { createWorkerRPCChannel };
25
+ //# sourceMappingURL=worker-rpc-channel-lbhK7Qz8.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-rpc-channel-lbhK7Qz8.mjs","names":[],"sources":["../src/pool/worker-rpc-channel.ts"],"sourcesContent":["import { MessageChannel } from 'node:worker_threads';\nimport { createBirpc } from 'birpc';\nimport type { RunnerRPC, RuntimeRPC } from 'vitest';\nimport { type TestProject, createMethodsRPC } from 'vitest/node';\n\nimport type { WorkerChannel } from '../types/types.js';\n\n/**\n * Create a MessageChannel with RPC for worker thread communication\n */\nexport function createWorkerRPCChannel(project: TestProject, collect: boolean): WorkerChannel {\n const channel = new MessageChannel();\n const workerPort = channel.port1;\n const poolPort = channel.port2;\n\n const methods = createMethodsRPC(project, { collect });\n\n // Create RPC in pool\n const rpc = createBirpc<RuntimeRPC, RunnerRPC>(\n methods,\n {\n post: (v) => poolPort.postMessage(v),\n on: (fn) => poolPort.on('message', fn),\n }\n );\n\n return { workerPort, poolPort, rpc };\n}\n"],"mappings":";;;;;;;;AAUA,SAAgB,uBAAuB,SAAsB,SAAiC;CAC5F,MAAM,UAAU,IAAI,gBAAgB;CACpC,MAAM,aAAa,QAAQ;CAC3B,MAAM,WAAW,QAAQ;AAazB,QAAO;EAAE;EAAY;EAAU,KARnB,YAHI,iBAAiB,SAAS,EAAE,SAAS,CAAC,EAKpD;GACE,OAAO,MAAM,SAAS,YAAY,EAAE;GACpC,KAAK,OAAO,SAAS,GAAG,WAAW,GAAG;GACvC,CACF;EAEmC"}
package/package.json ADDED
@@ -0,0 +1,112 @@
1
+ {
2
+ "name": "vitest-pool-assemblyscript",
3
+ "version": "0.2.0",
4
+ "description": "AssemblyScript testing with Vitest - Simple, fast, familiar, AS-native, with full coverage output",
5
+ "type": "module",
6
+ "main": "./dist/index.mjs",
7
+ "types": "./dist/index.d.mts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.mts",
11
+ "default": "./dist/index.mjs"
12
+ },
13
+ "./config": {
14
+ "types": "./dist/config/index.d.mts",
15
+ "default": "./dist/config/index.mjs"
16
+ },
17
+ "./v3": {
18
+ "types": "./dist/index-v3.d.mts",
19
+ "default": "./dist/index-v3.mjs"
20
+ },
21
+ "./v3/config": {
22
+ "types": "./dist/config/index-v3.d.mts",
23
+ "default": "./dist/config/index-v3.mjs"
24
+ },
25
+ "./coverage": {
26
+ "types": "./dist/coverage-provider/index.d.mts",
27
+ "default": "./dist/coverage-provider/index.mjs"
28
+ },
29
+ "./assembly": {
30
+ "types": "./assembly/index.mts",
31
+ "default": "./assembly/index.mts"
32
+ },
33
+ "./__internal": {
34
+ "types": "./dist/internal-test-entry.d.mts",
35
+ "default": "./dist/internal-test-entry.mjs"
36
+ }
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "prebuilds",
41
+ "binding.gyp",
42
+ "src/native-instrumentation/addon.cpp",
43
+ "scripts/setup-binaryen.js",
44
+ "scripts/install.js",
45
+ "BINARYEN_VERSION",
46
+ "assembly"
47
+ ],
48
+ "engines": {
49
+ "node": ">=20.0.0"
50
+ },
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/themattspiral/vitest-pool-assemblyscript.git"
54
+ },
55
+ "bugs": {
56
+ "url": "https://github.com/themattspiral/vitest-pool-assemblyscript/issues"
57
+ },
58
+ "homepage": "https://github.com/themattspiral/vitest-pool-assemblyscript#readme",
59
+ "scripts": {
60
+ "build": "tsdown",
61
+ "tc": "tsc --noEmit",
62
+ "//------------ Testing ------------": "",
63
+ "test": "vitest run",
64
+ "test:watch": "vitest",
65
+ "test:fixtures": "npm run testf",
66
+ "testf": "vitest run -c test-fixtures/vitest.config.ts",
67
+ "//------------ Native Addon ------------": "",
68
+ "setup-binaryen": "node scripts/setup-binaryen.js",
69
+ "build:native": "node-gyp rebuild",
70
+ "build:prebuilds": "prebuildify --napi --strip --tag-libc",
71
+ "install": "node scripts/install.js"
72
+ },
73
+ "dependencies": {
74
+ "birpc": "^4.0.0",
75
+ "node-addon-api": "^8.5.0",
76
+ "node-gyp-build": "^4.8.0",
77
+ "source-map": "^0.7.6",
78
+ "test-exclude": "^7.0.1",
79
+ "tinypool": "^2.1.0",
80
+ "tinyrainbow": "^3.0.3"
81
+ },
82
+ "peerDependencies": {
83
+ "@vitest/coverage-v8": "^3.2.0 || ^4.0.0",
84
+ "@vitest/runner": "^3.2.0 || ^4.0.0",
85
+ "@vitest/utils": "^3.2.0 || ^4.0.0",
86
+ "assemblyscript": "^0.28.9",
87
+ "istanbul-lib-coverage": "^3.2.2",
88
+ "vitest": "^3.2.0 || ^4.0.0"
89
+ },
90
+ "devDependencies": {
91
+ "@semantic-release/github": "^12.0.3",
92
+ "@semantic-release/npm": "^13.1.3",
93
+ "@types/istanbul-lib-coverage": "^2.0.6",
94
+ "@types/node": "22.19.1",
95
+ "@types/semver": "^7.7.1",
96
+ "@types/source-map": "^0.5.2",
97
+ "@types/test-exclude": "^6.0.2",
98
+ "@vitest/coverage-v8": "^4.0.18",
99
+ "@vitest/runner": "^4.0.18",
100
+ "@vitest/utils": "^4.0.18",
101
+ "assemblyscript": "^0.28.9",
102
+ "conventional-changelog-conventionalcommits": "^9.1.0",
103
+ "istanbul-lib-coverage": "^3.2.2",
104
+ "node-gyp": "^12.2.0",
105
+ "prebuildify": "^6.0.1",
106
+ "semantic-release": "^25.0.3",
107
+ "tsdown": "^0.20.1",
108
+ "tsx": "^4.21.0",
109
+ "typescript": "^5.9.3",
110
+ "vitest": "^4.0.18"
111
+ }
112
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Custom install script for vitest-pool-assemblyscript native addon.
3
+ *
4
+ * Flow:
5
+ * 1. Try to load a prebuilt or locally-built native addon via node-gyp-build
6
+ * 2. If found → clean up non-matching prebuilds to save disk space, then exit
7
+ * 3. If not found → download Binaryen dependencies, then compile from source
8
+ *
9
+ * This makes installation seamless for users on unsupported platforms:
10
+ * they only need a C++ compiler toolchain (standard for native Node.js addons).
11
+ */
12
+
13
+ import { execSync } from 'child_process';
14
+ import { createRequire } from 'node:module';
15
+ import { resolve, dirname, join } from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+ import { readdirSync, rmSync, existsSync } from 'node:fs';
18
+
19
+ const __filename = fileURLToPath(import.meta.url);
20
+ const __dirname = dirname(__filename);
21
+ const packageRoot = resolve(__dirname, '..');
22
+
23
+ const require = createRequire(import.meta.url);
24
+
25
+ /**
26
+ * Remove prebuild directories that don't match the current platform.
27
+ * Prebuilds ship for all 6 platforms (~21 MB each uncompressed), but only
28
+ * the current platform's prebuild is needed at runtime.
29
+ */
30
+ function cleanUnusedPrebuilds() {
31
+ const prebuildsDir = join(packageRoot, 'prebuilds');
32
+ if (!existsSync(prebuildsDir)) return;
33
+
34
+ const currentPlatformDir = `${process.platform}-${process.arch}`;
35
+
36
+ try {
37
+ const entries = readdirSync(prebuildsDir);
38
+ for (const entry of entries) {
39
+ if (entry !== currentPlatformDir) {
40
+ rmSync(join(prebuildsDir, entry), { recursive: true, force: true });
41
+ }
42
+ }
43
+ } catch {
44
+ // Non-critical — don't fail install over cleanup
45
+ }
46
+ }
47
+
48
+ // Step 1: Check if a prebuild or local build already exists
49
+ try {
50
+ const nodeGypBuild = require('node-gyp-build');
51
+ nodeGypBuild(packageRoot);
52
+ // Addon loaded successfully — clean up unused prebuilds and exit
53
+ cleanUnusedPrebuilds();
54
+ process.exit(0);
55
+ } catch {
56
+ // No prebuild or local build found — fall through to source build
57
+ }
58
+
59
+ // Step 2: Download Binaryen headers and static library
60
+ console.log('No prebuilt native addon found for this platform. Building from source...');
61
+ console.log('');
62
+
63
+ try {
64
+ console.log('Downloading Binaryen dependencies...');
65
+ execSync('node scripts/setup-binaryen.js', {
66
+ cwd: packageRoot,
67
+ stdio: 'inherit',
68
+ });
69
+ } catch (err) {
70
+ console.error('Failed to download Binaryen dependencies.');
71
+ console.error('The native addon is required for vitest-pool-assemblyscript.');
72
+ console.error(err instanceof Error ? err.message : String(err));
73
+ process.exit(1);
74
+ }
75
+
76
+ // Step 3: Compile native addon from source
77
+ try {
78
+ console.log('');
79
+ console.log('Compiling native addon...');
80
+ execSync('node-gyp rebuild', {
81
+ cwd: packageRoot,
82
+ stdio: 'inherit',
83
+ });
84
+ console.log('');
85
+ console.log('Native addon compiled successfully.');
86
+ } catch (err) {
87
+ console.error('Failed to compile native addon from source.');
88
+ console.error('Ensure a C++ compiler toolchain is installed (see https://github.com/nodejs/node-gyp#installation).');
89
+ console.error(err instanceof Error ? err.message : String(err));
90
+ process.exit(1);
91
+ }
@@ -0,0 +1,179 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import https from 'https';
4
+ import { execSync } from 'child_process';
5
+
6
+ // Read version from BINARYEN_VERSION file
7
+ const BINARYEN_VERSION = fs.readFileSync(
8
+ path.join(import.meta.dirname, '..', 'BINARYEN_VERSION'),
9
+ 'utf8'
10
+ ).trim();
11
+
12
+ // Detect platform for prebuilt binaries
13
+ function detectPlatform() {
14
+ const platform = process.platform;
15
+ const arch = process.arch;
16
+
17
+ if (platform === 'linux' && arch === 'x64') {
18
+ return 'x86_64-linux';
19
+ } else if (platform === 'linux' && arch === 'arm64') {
20
+ return 'aarch64-linux';
21
+ } else if (platform === 'darwin' && arch === 'x64') {
22
+ return 'x86_64-macos';
23
+ } else if (platform === 'darwin' && arch === 'arm64') {
24
+ return 'arm64-macos';
25
+ } else if (platform === 'win32' && arch === 'x64') {
26
+ return 'x86_64-windows';
27
+ } else if (platform === 'win32' && arch === 'arm64') {
28
+ return 'arm64-windows';
29
+ } else {
30
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
31
+ }
32
+ }
33
+
34
+ const PLATFORM = detectPlatform();
35
+ const PREBUILT_URL = `https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VERSION}/binaryen-${BINARYEN_VERSION}-${PLATFORM}.tar.gz`;
36
+ const SOURCE_URL = `https://github.com/WebAssembly/binaryen/archive/refs/tags/${BINARYEN_VERSION}.tar.gz`;
37
+ const PREBUILT_ARCHIVE = path.join(import.meta.dirname, '..', 'binaryen-prebuilt.tar.gz');
38
+ const SOURCE_ARCHIVE = path.join(import.meta.dirname, '..', 'binaryen-source.tar.gz');
39
+ const THIRD_PARTY_DIR = path.join(import.meta.dirname, '..', 'third_party');
40
+ const BINARYEN_DIR = path.join(THIRD_PARTY_DIR, 'binaryen');
41
+ const TEMP_DIR = path.join(THIRD_PARTY_DIR, 'binaryen-temp');
42
+
43
+ console.log(`Setting up Binaryen ${BINARYEN_VERSION}...`);
44
+ console.log(`Platform: ${PLATFORM}`);
45
+ console.log('');
46
+
47
+ // Step 1: Download prebuilt binaries
48
+ console.log('Step 1: Downloading prebuilt binaries...');
49
+ console.log(`URL: ${PREBUILT_URL}`);
50
+ downloadFile(PREBUILT_URL, PREBUILT_ARCHIVE, () => {
51
+ console.log('✓ Prebuilt binaries downloaded');
52
+ console.log('');
53
+
54
+ // Step 2: Download source code (for C++ headers)
55
+ console.log('Step 2: Downloading source code for headers...');
56
+ console.log(`URL: ${SOURCE_URL}`);
57
+ downloadFile(SOURCE_URL, SOURCE_ARCHIVE, () => {
58
+ console.log('✓ Source code downloaded');
59
+ console.log('');
60
+
61
+ extractAndCombine();
62
+ });
63
+ });
64
+
65
+ function downloadFile(url, dest, callback) {
66
+ const file = fs.createWriteStream(dest);
67
+
68
+ const handleResponse = (response) => {
69
+ response.pipe(file);
70
+ file.on('finish', () => {
71
+ file.close(() => {
72
+ response.destroy();
73
+ callback();
74
+ });
75
+ });
76
+ file.on('error', (err) => {
77
+ response.destroy();
78
+ if (fs.existsSync(dest)) {
79
+ fs.unlinkSync(dest);
80
+ }
81
+ console.error(`File write failed: ${err.message}`);
82
+ process.exit(1);
83
+ });
84
+ };
85
+
86
+ const request = https.get(url, (response) => {
87
+ if (response.statusCode === 302 || response.statusCode === 301) {
88
+ // Follow redirect
89
+ response.destroy();
90
+ const redirectRequest = https.get(response.headers.location, handleResponse);
91
+ redirectRequest.on('error', (err) => {
92
+ if (fs.existsSync(dest)) {
93
+ fs.unlinkSync(dest);
94
+ }
95
+ console.error(`Download failed: ${err.message}`);
96
+ process.exit(1);
97
+ });
98
+ } else {
99
+ handleResponse(response);
100
+ }
101
+ });
102
+
103
+ request.on('error', (err) => {
104
+ if (fs.existsSync(dest)) {
105
+ fs.unlinkSync(dest);
106
+ }
107
+ console.error(`Download failed: ${err.message}`);
108
+ process.exit(1);
109
+ });
110
+ }
111
+
112
+ function extractAndCombine() {
113
+ console.log('Step 3: Extracting and combining...');
114
+
115
+ // Create directories
116
+ if (!fs.existsSync(THIRD_PARTY_DIR)) {
117
+ fs.mkdirSync(THIRD_PARTY_DIR, { recursive: true });
118
+ }
119
+ if (!fs.existsSync(TEMP_DIR)) {
120
+ fs.mkdirSync(TEMP_DIR, { recursive: true });
121
+ }
122
+
123
+ // Remove existing binaryen directory if it exists
124
+ if (fs.existsSync(BINARYEN_DIR)) {
125
+ fs.rmSync(BINARYEN_DIR, { recursive: true, force: true });
126
+ }
127
+
128
+ try {
129
+ // Extract prebuilt binaries
130
+ console.log(' Extracting prebuilt binaries...');
131
+ execSync(`tar -xzf "${PREBUILT_ARCHIVE}" -C "${THIRD_PARTY_DIR}"`, { stdio: 'pipe' });
132
+ const prebuiltDir = path.join(THIRD_PARTY_DIR, `binaryen-${BINARYEN_VERSION}`);
133
+ fs.renameSync(prebuiltDir, BINARYEN_DIR);
134
+
135
+ // Extract source code to temp
136
+ console.log(' Extracting source code...');
137
+ execSync(`tar -xzf "${SOURCE_ARCHIVE}" -C "${TEMP_DIR}"`, { stdio: 'pipe' });
138
+ const sourceDir = path.join(TEMP_DIR, `binaryen-${BINARYEN_VERSION}`);
139
+
140
+ // Copy src/ directory from source to our binaryen dir (for C++ headers)
141
+ console.log(' Copying C++ headers from source...');
142
+ const sourceSrcDir = path.join(sourceDir, 'src');
143
+ const destSrcDir = path.join(BINARYEN_DIR, 'src');
144
+
145
+ if (fs.existsSync(sourceSrcDir)) {
146
+ fs.cpSync(sourceSrcDir, destSrcDir, { recursive: true });
147
+ } else {
148
+ throw new Error('Source src/ directory not found');
149
+ }
150
+
151
+ // Clean up
152
+ console.log(' Cleaning up...');
153
+ fs.rmSync(TEMP_DIR, { recursive: true, force: true });
154
+ fs.unlinkSync(PREBUILT_ARCHIVE);
155
+ fs.unlinkSync(SOURCE_ARCHIVE);
156
+
157
+ console.log('');
158
+ console.log(`✓ Binaryen ${BINARYEN_VERSION} installed to third_party/binaryen`);
159
+ console.log('');
160
+ console.log('Contents:');
161
+ const contents = fs.readdirSync(BINARYEN_DIR);
162
+ console.log(contents.map(f => ` ${f}`).join('\n'));
163
+
164
+ const libDir = path.join(BINARYEN_DIR, 'lib');
165
+ if (fs.existsSync(libDir)) {
166
+ console.log('');
167
+ console.log('Library files:');
168
+ const libFiles = fs.readdirSync(libDir);
169
+ console.log(libFiles.map(f => ` ${f}`).join('\n'));
170
+ }
171
+
172
+ console.log('');
173
+ console.log('Setup complete!');
174
+ } catch (err) {
175
+ console.error('Extraction/combination failed:', err.message);
176
+ console.error('Make sure tar is available on your system.');
177
+ process.exit(1);
178
+ }
179
+ }