quickjs-zig 1.0.2 → 1.0.3

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 (3) hide show
  1. package/README.md +33 -6
  2. package/build.mjs +30 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,9 +5,10 @@ A high-performance build system for **QuickJS**, powered by the **Zig** compiler
5
5
  ## Features
6
6
 
7
7
  * **Zero Config Cross-Compilation**: Build for Windows, Linux, and macOS from any host (Intel or Apple Silicon).
8
- * **Zig-Powered**: Uses **Zig 0.15.2** as a C compiler for modern, safe, and highly optimized binaries.
8
+ * **Zig-Powered Optimization**: Uses **Zig 0.15.2** with LTO (Link Time Optimization) to produce small binaries.
9
9
  * **Custom C Modules**: Easily inject and register your own C modules into the QuickJS engine.
10
10
  * **Native Windows Support**: Includes a custom `exec` implementation for Windows, bypassing typical QuickJS POSIX limitations.
11
+ * **Platform-Specific Swapping**: Automatically replaces generic JS files with platform-specific ones (e.g., `index.mjs` → `index.darwin.mjs`) during build.
11
12
  * **Clean Source Management**: Automatically patches and restores QuickJS source files to keep the core library pristine.
12
13
 
13
14
  ---
@@ -35,17 +36,40 @@ npm link
35
36
 
36
37
  ```
37
38
 
39
+ ---
40
+
41
+ ## Platform-Specific File Swapping
42
+
43
+ The build system supports platform-specific file resolution. This is useful when you need different JS logic for different operating systems while maintaining a single development entry point for IDE completion.
44
+
45
+ ### How it works
46
+
47
+ 1. **Generic file**: Create a base file (e.g., `index.mjs` or `dialogs.mjs`). This is your reference for IDE completion and IntelliSense.
48
+ 2. **Specific files**: Create files with the platform suffix:
49
+ * `filename.win32.mjs`
50
+ * `filename.darwin.mjs`
51
+ * `filename.linux.mjs`
52
+
53
+
54
+ 3. **Build Logic**:
55
+ * The `build/` folder is cleaned at the start of each execution.
56
+ * If a platform-specific version exists, the generic version is **excluded** from the build folder to avoid duplicates.
57
+ * The script automatically rewrites `import` statements in your code to point to the correct suffix during the build process.
58
+
59
+
60
+
38
61
  ---
39
62
 
40
63
  ## Configuration
41
64
 
42
- Configure your entry point and custom C modules in your project's `package.json`:
65
+ Configure your entry point, optimization, and custom C modules in your project's `package.json`:
43
66
 
44
67
  ```json
45
68
  {
46
69
  "name": "my-app",
47
70
  "quickJs": {
48
71
  "input": "app/index.mjs",
72
+ "optimization": true,
49
73
  "modules": {
50
74
  "my_module": "src/my_module.c"
51
75
  }
@@ -55,8 +79,11 @@ Configure your entry point and custom C modules in your project's `package.json`
55
79
  ```
56
80
 
57
81
  * **`input`**: The entry point of your JavaScript application (defaults to `app/index.mjs`).
82
+ * **`optimization`**: When `true`, enables **LTO**, aggressive inlining (`-O3`), and strips unused features like `eval` or `Promises` via `qjsc` flags.
58
83
  * **`modules`**: A key-value map of custom C modules (Module Name -> C Source Path).
59
84
 
85
+ **Note**: The system always applies `-s` (strip symbols) regardless of the optimization flag to ensure no `.pdb` or debug tables are generated.
86
+
60
87
  ---
61
88
 
62
89
  ## Example Usage
@@ -130,9 +157,9 @@ The build system generates binaries for the following platforms in the `dist/` f
130
157
 
131
158
  Zig is not just a language; it's a powerful C/C++ toolchain. It allows `quickjs-zig` to:
132
159
 
133
- * Cross-compile to Windows (MinGW) from macOS/Linux without installing complex toolchains.
134
- * Provide a consistent `libc` environment across different platforms.
135
- * Produce small, fast, and statically linked binaries.
160
+ * **Cross-compile** to Windows (MinGW) or Linux from any host without installing complex toolchains.
161
+ * **Size matters**: By using `-flto` and `-O3`, Zig can discard unused parts of the engine, bringing the footprint down by nearly 95% compared to Node.js standalone binaries.
162
+ * **macOS LTO Support**: On Apple targets, we automatically force `-fuse-ld=lld` when optimized to ensure the LLVM Linker handles the bitcode correctly.
136
163
 
137
164
  ### Windows Patching
138
165
 
@@ -144,4 +171,4 @@ QuickJS is designed for POSIX systems. This tool automatically patches `quickjs-
144
171
 
145
172
  MIT - Created by **eid-app**.
146
173
 
147
- ---
174
+ ---
package/build.mjs CHANGED
@@ -26,17 +26,23 @@ const userPackageJson = JSON.parse(readFileSync(USER_PKG_PATH, 'utf8'));
26
26
  const customModules = userPackageJson.quickJs?.modules || {};
27
27
  const APP_NAME = userPackageJson.name || 'app';
28
28
 
29
+ // Optimization flag from package.json
30
+ const IS_OPTIMIZED = userPackageJson.quickJs?.optimization === true;
31
+
29
32
  // Input file from package.json or default to app/index.mjs
30
33
  const INPUT_FILE_RELATIVE = userPackageJson.quickJs?.input || 'app/index.mjs';
31
34
 
32
35
  /**
33
36
  * Recursively scan and transform imports to platform-specific ones.
34
- * Filters out files from other platforms and prevents duplicates.
37
+ * Filters out files from other platforms and ensures specific versions
38
+ * replace generic ones (like index.mjs) in the build folder.
35
39
  */
36
40
  function processDirectory(currentDir, targetDir, targetPlat) {
37
41
  if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
38
42
 
39
- readdirSync(currentDir).forEach(file => {
43
+ const filesInSource = readdirSync(currentDir);
44
+
45
+ filesInSource.forEach(file => {
40
46
  const fullPath = path.join(currentDir, file);
41
47
  const destPath = path.join(targetDir, file);
42
48
 
@@ -56,17 +62,18 @@ function processDirectory(currentDir, targetDir, targetPlat) {
56
62
  return;
57
63
  }
58
64
 
59
- // 2. If it's a generic file, skip it if a platform-specific version exists in the same folder
65
+ // 2. Logic for generic files (like index.mjs):
66
+ // If a specific version (index.darwin.mjs) exists, we skip the generic one.
60
67
  if (!filePlat || !knownPlats.includes(filePlat)) {
61
68
  const specFile = file.replace(/\.mjs$/, `.${targetPlat}.mjs`);
62
- if (readdirSync(currentDir).includes(specFile)) {
69
+ if (filesInSource.includes(specFile)) {
63
70
  return;
64
71
  }
65
72
  }
66
73
 
67
74
  let content = readFileSync(fullPath, 'utf8');
68
75
 
69
- // 3. Transform generic imports to platform-specific ones if they exist
76
+ // 3. Transform generic imports to platform-specific ones if they exist physically
70
77
  content = content.replace(/(import\s+.+?\s+from\s+['"])(.+?)\.mjs(['"])/g, (match, before, importPath, after) => {
71
78
  const platFile = `${importPath}.${targetPlat}.mjs`;
72
79
  const platformFullPath = path.resolve(currentDir, platFile);
@@ -185,8 +192,11 @@ const targets = [
185
192
  const stubPath = path.join(QUICKJS_DIR, 'repl_stub.c');
186
193
  writeFileSync(stubPath, `const unsigned char qjsc_repl[] = {0}; const unsigned int qjsc_repl_size = 0;`);
187
194
 
195
+ // Feature optimization flags for qjsc
196
+ const qjscFlags = IS_OPTIMIZED ? '-fno-eval -fno-regexp -fno-proxy -fno-map -fno-typedarray -fno-promise' : '';
197
+
188
198
  targets.forEach(t => {
189
- console.log(`\n--- Compiling for: ${t.id} (Suffix: ${t.plat}) ---`);
199
+ console.log(`\n--- Compiling for: ${t.id} ---`);
190
200
 
191
201
  // --- PLATFORM SPECIFIC BUILD RESOLUTION ---
192
202
  const PLATFORM_BUILD_DIR = path.join(USER_CWD, 'build', t.id);
@@ -200,7 +210,15 @@ targets.forEach(t => {
200
210
 
201
211
  const TARGET_INPUT_ABS = path.join(PLATFORM_BUILD_DIR, path.basename(INPUT_FILE_RELATIVE));
202
212
 
203
- const cmdBase = `${ZIG_PATH} cc -target ${t.id} -I${QUICKJS_DIR} -O2 ${t.cflags} -Wno-ignored-attributes -DCONFIG_VERSION=\\"${VERSION}\\" ${t.libs} -s`;
213
+ // Dynamic Optimization Flags
214
+ let optFlags = IS_OPTIMIZED ? '-O3 -flto' : '-O2';
215
+
216
+ // -fuse-ld=lld is mandatory for macOS LTO, but causes warnings on other platforms
217
+ if (IS_OPTIMIZED && t.plat === 'darwin') {
218
+ optFlags += ' -fuse-ld=lld';
219
+ }
220
+
221
+ const cmdBase = `${ZIG_PATH} cc -target ${t.id} -I${QUICKJS_DIR} ${optFlags} ${t.cflags} -Wno-ignored-attributes -DCONFIG_VERSION=\\"${VERSION}\\" ${t.libs} -s`;
204
222
 
205
223
  try {
206
224
  execSync(`${cmdBase} -o "${path.join(BIN_DIR, t.qjs)}" ${baseSources} ${stubPath} "${path.join(QUICKJS_DIR, 'qjs.c')}"`);
@@ -209,11 +227,11 @@ targets.forEach(t => {
209
227
 
210
228
  const tempC = path.join(BIN_DIR, `${t.id}_app.c`);
211
229
 
212
- // Use host qjsc to compile the platform-specific source
213
- execSync(`"${hostQjscPath}" -e -o "${tempC}" "${TARGET_INPUT_ABS}"`, { cwd: USER_CWD });
230
+ // Use host qjsc to compile the platform-resolved source
231
+ execSync(`"${hostQjscPath}" ${qjscFlags} -e -o "${tempC}" "${TARGET_INPUT_ABS}"`, { cwd: USER_CWD });
214
232
 
215
233
  execSync(`${cmdBase} -o "${path.join(DIST_DIR, t.app)}" "${tempC}" ${baseSources} -I${QUICKJS_DIR}`);
216
- console.log(`✅ Binary built: ${t.app}`);
234
+ console.log(`✅ Binary built${IS_OPTIMIZED ? ' and optimized' : ''}: ${t.app}`);
217
235
  } catch (e) {
218
236
  console.error(`❌ Compilation failed for ${t.id}`);
219
237
  console.error(e.stderr?.toString() || e.message);
@@ -242,4 +260,5 @@ binFiles.forEach(file => {
242
260
  });
243
261
  if (existsSync(stubPath)) unlinkSync(stubPath);
244
262
 
245
- console.log("🚀 Build process complete. Platform sources kept in build/ subfolders.");
263
+ console.log(`🚀 Build process complete. (Optimization: ${IS_OPTIMIZED ? 'ON' : 'OFF'})`);
264
+ console.log("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.2",
3
+ "version": "1.0.3",
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",