quickjs-zig 1.0.0 → 1.0.2

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/build.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { execSync } from 'child_process';
2
- import { writeFileSync, mkdirSync, unlinkSync, existsSync, readdirSync, cpSync, readFileSync, renameSync } from 'fs';
2
+ import { writeFileSync, mkdirSync, unlinkSync, existsSync, readdirSync, cpSync, readFileSync, renameSync, statSync, rmSync } from 'fs';
3
3
  import path from 'path';
4
4
  import os from 'os';
5
5
  import { fileURLToPath } from 'url';
@@ -7,6 +7,13 @@ import { fileURLToPath } from 'url';
7
7
  // --- PATH CONFIGURATION ---
8
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
9
  const USER_CWD = process.cwd();
10
+ const PLATFORM = os.platform();
11
+
12
+ // Clean global build directory at the very beginning
13
+ const GLOBAL_BUILD_DIR = path.join(USER_CWD, 'build');
14
+ if (existsSync(GLOBAL_BUILD_DIR)) {
15
+ rmSync(GLOBAL_BUILD_DIR, { recursive: true });
16
+ }
10
17
 
11
18
  // Load the user project's package.json
12
19
  const USER_PKG_PATH = path.join(USER_CWD, 'package.json');
@@ -21,11 +28,62 @@ const APP_NAME = userPackageJson.name || 'app';
21
28
 
22
29
  // Input file from package.json or default to app/index.mjs
23
30
  const INPUT_FILE_RELATIVE = userPackageJson.quickJs?.input || 'app/index.mjs';
24
- const INPUT_FILE_ABS = path.resolve(USER_CWD, INPUT_FILE_RELATIVE);
25
31
 
26
- if (!existsSync(INPUT_FILE_ABS)) {
27
- console.error(`❌ Error: Input file not found at ${INPUT_FILE_ABS}`);
28
- process.exit(1);
32
+ /**
33
+ * Recursively scan and transform imports to platform-specific ones.
34
+ * Filters out files from other platforms and prevents duplicates.
35
+ */
36
+ function processDirectory(currentDir, targetDir, targetPlat) {
37
+ if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
38
+
39
+ readdirSync(currentDir).forEach(file => {
40
+ const fullPath = path.join(currentDir, file);
41
+ const destPath = path.join(targetDir, file);
42
+
43
+ if (statSync(fullPath).isDirectory()) {
44
+ return processDirectory(fullPath, destPath, targetPlat);
45
+ }
46
+
47
+ const isMjs = file.endsWith('.mjs') || file.endsWith('.js');
48
+ const knownPlats = ['win32', 'darwin', 'linux'];
49
+
50
+ if (isMjs) {
51
+ const parts = file.split('.');
52
+ const filePlat = parts.length > 2 ? parts[parts.length - 2] : null;
53
+
54
+ // 1. Skip files belonging to OTHER platforms
55
+ if (filePlat && knownPlats.includes(filePlat) && filePlat !== targetPlat) {
56
+ return;
57
+ }
58
+
59
+ // 2. If it's a generic file, skip it if a platform-specific version exists in the same folder
60
+ if (!filePlat || !knownPlats.includes(filePlat)) {
61
+ const specFile = file.replace(/\.mjs$/, `.${targetPlat}.mjs`);
62
+ if (readdirSync(currentDir).includes(specFile)) {
63
+ return;
64
+ }
65
+ }
66
+
67
+ let content = readFileSync(fullPath, 'utf8');
68
+
69
+ // 3. Transform generic imports to platform-specific ones if they exist
70
+ content = content.replace(/(import\s+.+?\s+from\s+['"])(.+?)\.mjs(['"])/g, (match, before, importPath, after) => {
71
+ const platFile = `${importPath}.${targetPlat}.mjs`;
72
+ const platformFullPath = path.resolve(currentDir, platFile);
73
+
74
+ if (existsSync(platformFullPath)) {
75
+ console.log(`✨ [${targetPlat}] Swapping import: ${importPath}.mjs -> ${platFile}`);
76
+ return `${before}${importPath}.${targetPlat}.mjs${after}`;
77
+ }
78
+ return match;
79
+ });
80
+
81
+ writeFileSync(destPath, content);
82
+ } else {
83
+ // Copy assets and other files as is
84
+ cpSync(fullPath, destPath);
85
+ }
86
+ });
29
87
  }
30
88
 
31
89
  const QUICKJS_DIR = path.resolve(__dirname, 'quickjs');
@@ -46,13 +104,11 @@ if (!existsSync(BIN_DIR)) mkdirSync(BIN_DIR, { recursive: true });
46
104
  if (!existsSync(DIST_DIR)) mkdirSync(DIST_DIR, { recursive: true });
47
105
 
48
106
  // Detect the host architecture to find the correct qjsc binary
49
- const platform = os.platform();
50
107
  const arch = os.arch();
51
108
  let hostQjscName = '';
52
-
53
- if (platform === 'darwin') hostQjscName = (arch === 'arm64') ? 'qjsc_mac_arm' : 'qjsc_mac_intel';
54
- else if (platform === 'linux') hostQjscName = (arch === 'arm64' || arch === 'aarch64') ? 'qjsc_linux_arm' : 'qjsc_linux64';
55
- else if (platform === 'win32') hostQjscName = 'qjsc_win64.exe';
109
+ if (PLATFORM === 'darwin') hostQjscName = (arch === 'arm64') ? 'qjsc_mac_arm' : 'qjsc_mac_intel';
110
+ else if (PLATFORM === 'linux') hostQjscName = (arch === 'arm64' || arch === 'aarch64') ? 'qjsc_linux_arm' : 'qjsc_linux64';
111
+ else if (PLATFORM === 'win32') hostQjscName = 'qjsc_win64.exe';
56
112
 
57
113
  const hostQjscPath = path.join(BIN_DIR, hostQjscName);
58
114
 
@@ -114,13 +170,13 @@ const baseSources = ['quickjs.c', 'libregexp.c', 'libunicode.c', 'cutils.c', 'qu
114
170
  .join(' ');
115
171
 
116
172
  const targets = [
117
- { id: 'x86_64-windows-gnu', qjs: 'qjs_win64.exe', qjsc: 'qjsc_win64.exe', app: `${APP_NAME}_win64.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE' },
118
- { id: 'x86-windows-gnu', qjs: 'qjs_win32.exe', qjsc: 'qjsc_win32.exe', app: `${APP_NAME}_win32.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE' },
119
- { id: 'x86_64-linux-gnu', qjs: 'qjs_linux64', qjsc: 'qjsc_linux64', app: `${APP_NAME}_linux64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' },
120
- { id: 'x86-linux-gnu', qjs: 'qjs_linux32', qjsc: 'qjsc_linux32', app: `${APP_NAME}_linux32`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' },
121
- { id: 'aarch64-linux-gnu', qjs: 'qjs_linux_arm64', qjsc: 'qjsc_linux_arm64', app: `${APP_NAME}_linux_arm64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' },
122
- { id: 'aarch64-macos', qjs: 'qjs_mac_arm', qjsc: 'qjsc_mac_arm', app: `${APP_NAME}_mac_arm`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' },
123
- { id: 'x86_64-macos', qjs: 'qjs_mac_intel', qjsc: 'qjsc_mac_intel', app: `${APP_NAME}_mac_intel`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD' }
173
+ { id: 'x86_64-windows-gnu', qjs: 'qjs_win64.exe', qjsc: 'qjsc_win64.exe', app: `${APP_NAME}_win64.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE', plat: 'win32' },
174
+ { id: 'x86-windows-gnu', qjs: 'qjs_win32.exe', qjsc: 'qjsc_win32.exe', app: `${APP_NAME}_win32.exe`, libs: '-lm', cflags: '-D_GNU_SOURCE', plat: 'win32' },
175
+ { id: 'x86_64-linux-gnu', qjs: 'qjs_linux64', qjsc: 'qjsc_linux64', app: `${APP_NAME}_linux64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'linux' },
176
+ { id: 'x86-linux-gnu', qjs: 'qjs_linux32', qjsc: 'qjsc_linux32', app: `${APP_NAME}_linux32`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'linux' },
177
+ { id: 'aarch64-linux-gnu', qjs: 'qjs_linux_arm64', qjsc: 'qjsc_linux_arm64', app: `${APP_NAME}_linux_arm64`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'linux' },
178
+ { id: 'aarch64-macos', qjs: 'qjs_mac_arm', qjsc: 'qjsc_mac_arm', app: `${APP_NAME}_mac_arm`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'darwin' },
179
+ { id: 'x86_64-macos', qjs: 'qjs_mac_intel', qjsc: 'qjsc_mac_intel', app: `${APP_NAME}_mac_intel`, libs: '-lm -lpthread -ldl', cflags: '-D_GNU_SOURCE -DCONFIG_PTHREAD', plat: 'darwin' }
124
180
  ];
125
181
 
126
182
  // ==========================================================
@@ -130,7 +186,20 @@ const stubPath = path.join(QUICKJS_DIR, 'repl_stub.c');
130
186
  writeFileSync(stubPath, `const unsigned char qjsc_repl[] = {0}; const unsigned int qjsc_repl_size = 0;`);
131
187
 
132
188
  targets.forEach(t => {
133
- console.log(`\n--- Compiling for: ${t.id} ---`);
189
+ console.log(`\n--- Compiling for: ${t.id} (Suffix: ${t.plat}) ---`);
190
+
191
+ // --- PLATFORM SPECIFIC BUILD RESOLUTION ---
192
+ const PLATFORM_BUILD_DIR = path.join(USER_CWD, 'build', t.id);
193
+ const inputBaseDir = path.dirname(path.resolve(USER_CWD, INPUT_FILE_RELATIVE));
194
+
195
+ if (existsSync(PLATFORM_BUILD_DIR)) {
196
+ rmSync(PLATFORM_BUILD_DIR, { recursive: true });
197
+ }
198
+
199
+ processDirectory(inputBaseDir, PLATFORM_BUILD_DIR, t.plat);
200
+
201
+ const TARGET_INPUT_ABS = path.join(PLATFORM_BUILD_DIR, path.basename(INPUT_FILE_RELATIVE));
202
+
134
203
  const cmdBase = `${ZIG_PATH} cc -target ${t.id} -I${QUICKJS_DIR} -O2 ${t.cflags} -Wno-ignored-attributes -DCONFIG_VERSION=\\"${VERSION}\\" ${t.libs} -s`;
135
204
 
136
205
  try {
@@ -139,9 +208,9 @@ targets.forEach(t => {
139
208
  console.log(`✅ Build tools generated.`);
140
209
 
141
210
  const tempC = path.join(BIN_DIR, `${t.id}_app.c`);
142
- const relativeInput = path.relative(USER_CWD, INPUT_FILE_ABS);
143
211
 
144
- execSync(`"${hostQjscPath}" -e -o "${tempC}" "${relativeInput}"`, { cwd: USER_CWD });
212
+ // Use host qjsc to compile the platform-specific source
213
+ execSync(`"${hostQjscPath}" -e -o "${tempC}" "${TARGET_INPUT_ABS}"`, { cwd: USER_CWD });
145
214
 
146
215
  execSync(`${cmdBase} -o "${path.join(DIST_DIR, t.app)}" "${tempC}" ${baseSources} -I${QUICKJS_DIR}`);
147
216
  console.log(`✅ Binary built: ${t.app}`);
@@ -172,4 +241,5 @@ binFiles.forEach(file => {
172
241
  }
173
242
  });
174
243
  if (existsSync(stubPath)) unlinkSync(stubPath);
175
- console.log("🚀 Build process complete.");
244
+
245
+ console.log("🚀 Build process complete. Platform sources kept in build/ subfolders.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quickjs-zig",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A generic build engine to compile QuickJS scripts into standalone native binaries using Zig for multi-platform cross-compilation.",
5
5
  "type": "module",
6
6
  "main": "index.mjs",
package/postinstall.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { execSync } from 'child_process';
2
- import { mkdirSync, existsSync, writeFileSync, chmodSync, unlinkSync } from 'fs';
2
+ import { mkdirSync, existsSync, writeFileSync, chmodSync, unlinkSync, renameSync } from 'fs';
3
3
  import path from 'path';
4
4
  import os from 'os';
5
5
  import https from 'https';
@@ -9,6 +9,7 @@ import { fileURLToPath } from 'url';
9
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
10
  const ZIG_VERSION = '0.15.2';
11
11
  const BIN_DIR = path.resolve(__dirname, 'bin', 'zig');
12
+ const QUICKJS_DIR = path.resolve(__dirname, 'quickjs');
12
13
 
13
14
  // Mapping for Zig download URLs
14
15
  const platformMap = {
@@ -30,13 +31,16 @@ if (!platform || !arch) {
30
31
  process.exit(1);
31
32
  }
32
33
 
33
- // Fixed: Correct Zig URL order is arch-platform (e.g., x86_64-macos)
34
+ // Zig download configuration
34
35
  const zigTarget = `${arch}-${platform}`;
35
36
  const zigFileName = `zig-${zigTarget}-${ZIG_VERSION}.${platform === 'windows' ? 'zip' : 'tar.xz'}`;
36
37
  const zigUrl = `https://ziglang.org/download/${ZIG_VERSION}/${zigFileName}`;
37
-
38
38
  const ZIG_BIN_PATH = path.join(BIN_DIR, platform === 'windows' ? 'zig.exe' : 'zig');
39
39
 
40
+ // QuickJS source configuration (using zip for windows, tar.gz for unix)
41
+ const qjsExt = platform === 'windows' ? 'zip' : 'tar.gz';
42
+ const qjsUrl = `https://github.com/bellard/quickjs/archive/refs/heads/master.${qjsExt}`;
43
+
40
44
  // --- DOWNLOAD HELPER ---
41
45
  const downloadFile = (url, dest) => {
42
46
  return new Promise((resolve, reject) => {
@@ -62,13 +66,30 @@ const downloadFile = (url, dest) => {
62
66
  async function install() {
63
67
  console.log("=== POSTINSTALL: INITIALIZING PROJECT DEPENDENCIES ===");
64
68
 
65
- // 1. Initialize Git Submodules (QuickJS source)
66
- try {
67
- console.log("📂 Initializing git submodules...");
68
- execSync('git submodule update --init --recursive', { stdio: 'inherit' });
69
- console.log("✅ Submodules initialized.");
70
- } catch (err) {
71
- console.warn("⚠️ Git submodule update failed. Ensure you are in a git repository or have QuickJS sources.");
69
+ // 1. Download QuickJS source
70
+ if (!existsSync(QUICKJS_DIR)) {
71
+ try {
72
+ console.log(`📥 Downloading QuickJS source (${qjsExt})...`);
73
+ const qjsArchive = path.resolve(__dirname, `qjs.${qjsExt}`);
74
+ await downloadFile(qjsUrl, qjsArchive);
75
+
76
+ if (platform === 'windows') {
77
+ execSync(`powershell -command "Expand-Archive -Path '${qjsArchive}' -DestinationPath '${__dirname}' -Force"`);
78
+ } else {
79
+ execSync(`tar -xzf "${qjsArchive}" -C "${__dirname}"`);
80
+ }
81
+
82
+ const extractedDir = path.resolve(__dirname, 'quickjs-master');
83
+ if (existsSync(extractedDir)) {
84
+ renameSync(extractedDir, QUICKJS_DIR);
85
+ }
86
+ if (existsSync(qjsArchive)) unlinkSync(qjsArchive);
87
+ console.log("✅ QuickJS sources installed.");
88
+ } catch (err) {
89
+ console.error(`❌ Failed to install QuickJS: ${err.message}`);
90
+ }
91
+ } else {
92
+ console.log(`✅ QuickJS source already downloaded.`);
72
93
  }
73
94
 
74
95
  // 2. Install Zig Compiler
package/.gitmodules DELETED
@@ -1,3 +0,0 @@
1
- [submodule "quickjs"]
2
- path = quickjs
3
- url = https://github.com/bellard/quickjs