koffi 2.6.1 → 2.6.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/CHANGELOG.md +4 -0
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm32hf/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_riscv64hf64/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/contribute.md +2 -2
- package/doc/packaging.md +8 -0
- package/{src/index.js → index.js} +21 -20
- package/indirect.js +480 -0
- package/package.json +4 -4
- package/src/core/libcc/libcc.cc +41 -17
- /package/{src/index.d.ts → index.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/doc/contribute.md
CHANGED
|
@@ -138,8 +138,8 @@ First, you must update the code in three steps:
|
|
|
138
138
|
Once this is done, you can publish a new release with the following commands:
|
|
139
139
|
|
|
140
140
|
```sh
|
|
141
|
-
node qemu.js test # If not done before
|
|
142
|
-
node qemu.js dist
|
|
141
|
+
node tools/qemu.js test # If not done before
|
|
142
|
+
node tools/qemu.js dist
|
|
143
143
|
|
|
144
144
|
cd build/dist
|
|
145
145
|
npm publish
|
package/doc/packaging.md
CHANGED
|
@@ -36,6 +36,14 @@ resources/
|
|
|
36
36
|
MyApp.exe
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
## Indirect loader
|
|
40
|
+
|
|
41
|
+
*New in Koffi 2.6.2*
|
|
42
|
+
|
|
43
|
+
Some bundlers (such as vite) don't like when require is used with native modules.
|
|
44
|
+
|
|
45
|
+
In this case, you can use `js require('koffi/indirect')` but you will need to make sure that the native Koffi modules are packaged properly.
|
|
46
|
+
|
|
39
47
|
## Packaging examples
|
|
40
48
|
|
|
41
49
|
### Electron with electron-builder
|
|
@@ -378,8 +378,8 @@ var require_package = __commonJS({
|
|
|
378
378
|
"build/dist/src/koffi/package.json"(exports2, module2) {
|
|
379
379
|
module2.exports = {
|
|
380
380
|
name: "koffi",
|
|
381
|
-
version: "2.6.
|
|
382
|
-
stable: "2.6.
|
|
381
|
+
version: "2.6.2",
|
|
382
|
+
stable: "2.6.2",
|
|
383
383
|
description: "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
384
384
|
keywords: [
|
|
385
385
|
"foreign",
|
|
@@ -400,8 +400,8 @@ var require_package = __commonJS({
|
|
|
400
400
|
email: "niels.martignene@protonmail.com",
|
|
401
401
|
url: "https://koromix.dev/"
|
|
402
402
|
},
|
|
403
|
-
main: "
|
|
404
|
-
types: "
|
|
403
|
+
main: "./index.js",
|
|
404
|
+
types: "./index.d.ts",
|
|
405
405
|
scripts: {
|
|
406
406
|
test: "node tools/qemu.js test",
|
|
407
407
|
prepack: `echo 'Use "npm run prepare" instead' && false`,
|
|
@@ -430,7 +430,7 @@ var require_package = __commonJS({
|
|
|
430
430
|
}
|
|
431
431
|
});
|
|
432
432
|
|
|
433
|
-
// build/dist/src/koffi/
|
|
433
|
+
// build/dist/src/koffi/index.js
|
|
434
434
|
var util = require("util");
|
|
435
435
|
var fs = require("fs");
|
|
436
436
|
var { get_napi_version, determine_arch } = require_tools();
|
|
@@ -451,77 +451,77 @@ try {
|
|
|
451
451
|
switch (triplet) {
|
|
452
452
|
case "darwin_arm64":
|
|
453
453
|
{
|
|
454
|
-
native = require("
|
|
454
|
+
native = require("./build/koffi/darwin_arm64/koffi.node");
|
|
455
455
|
}
|
|
456
456
|
break;
|
|
457
457
|
case "darwin_x64":
|
|
458
458
|
{
|
|
459
|
-
native = require("
|
|
459
|
+
native = require("./build/koffi/darwin_x64/koffi.node");
|
|
460
460
|
}
|
|
461
461
|
break;
|
|
462
462
|
case "freebsd_arm64":
|
|
463
463
|
{
|
|
464
|
-
native = require("
|
|
464
|
+
native = require("./build/koffi/freebsd_arm64/koffi.node");
|
|
465
465
|
}
|
|
466
466
|
break;
|
|
467
467
|
case "freebsd_ia32":
|
|
468
468
|
{
|
|
469
|
-
native = require("
|
|
469
|
+
native = require("./build/koffi/freebsd_ia32/koffi.node");
|
|
470
470
|
}
|
|
471
471
|
break;
|
|
472
472
|
case "freebsd_x64":
|
|
473
473
|
{
|
|
474
|
-
native = require("
|
|
474
|
+
native = require("./build/koffi/freebsd_x64/koffi.node");
|
|
475
475
|
}
|
|
476
476
|
break;
|
|
477
477
|
case "linux_arm32hf":
|
|
478
478
|
{
|
|
479
|
-
native = require("
|
|
479
|
+
native = require("./build/koffi/linux_arm32hf/koffi.node");
|
|
480
480
|
}
|
|
481
481
|
break;
|
|
482
482
|
case "linux_arm64":
|
|
483
483
|
{
|
|
484
|
-
native = require("
|
|
484
|
+
native = require("./build/koffi/linux_arm64/koffi.node");
|
|
485
485
|
}
|
|
486
486
|
break;
|
|
487
487
|
case "linux_ia32":
|
|
488
488
|
{
|
|
489
|
-
native = require("
|
|
489
|
+
native = require("./build/koffi/linux_ia32/koffi.node");
|
|
490
490
|
}
|
|
491
491
|
break;
|
|
492
492
|
case "linux_riscv64hf64":
|
|
493
493
|
{
|
|
494
|
-
native = require("
|
|
494
|
+
native = require("./build/koffi/linux_riscv64hf64/koffi.node");
|
|
495
495
|
}
|
|
496
496
|
break;
|
|
497
497
|
case "linux_x64":
|
|
498
498
|
{
|
|
499
|
-
native = require("
|
|
499
|
+
native = require("./build/koffi/linux_x64/koffi.node");
|
|
500
500
|
}
|
|
501
501
|
break;
|
|
502
502
|
case "openbsd_ia32":
|
|
503
503
|
{
|
|
504
|
-
native = require("
|
|
504
|
+
native = require("./build/koffi/openbsd_ia32/koffi.node");
|
|
505
505
|
}
|
|
506
506
|
break;
|
|
507
507
|
case "openbsd_x64":
|
|
508
508
|
{
|
|
509
|
-
native = require("
|
|
509
|
+
native = require("./build/koffi/openbsd_x64/koffi.node");
|
|
510
510
|
}
|
|
511
511
|
break;
|
|
512
512
|
case "win32_arm64":
|
|
513
513
|
{
|
|
514
|
-
native = require("
|
|
514
|
+
native = require("./build/koffi/win32_arm64/koffi.node");
|
|
515
515
|
}
|
|
516
516
|
break;
|
|
517
517
|
case "win32_ia32":
|
|
518
518
|
{
|
|
519
|
-
native = require("
|
|
519
|
+
native = require("./build/koffi/win32_ia32/koffi.node");
|
|
520
520
|
}
|
|
521
521
|
break;
|
|
522
522
|
case "win32_x64":
|
|
523
523
|
{
|
|
524
|
-
native = require("
|
|
524
|
+
native = require("./build/koffi/win32_x64/koffi.node");
|
|
525
525
|
}
|
|
526
526
|
break;
|
|
527
527
|
}
|
|
@@ -529,6 +529,7 @@ try {
|
|
|
529
529
|
}
|
|
530
530
|
if (native == null) {
|
|
531
531
|
let names = [
|
|
532
|
+
`/build/koffi/${process.platform}_${arch}/koffi.node`,
|
|
532
533
|
`/koffi/${process.platform}_${arch}/koffi.node`,
|
|
533
534
|
`/node_modules/koffi/build/koffi/${process.platform}_${arch}/koffi.node`
|
|
534
535
|
];
|
package/indirect.js
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
4
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// build/dist/src/cnoke/src/tools.js
|
|
8
|
+
var require_tools = __commonJS({
|
|
9
|
+
"build/dist/src/cnoke/src/tools.js"(exports2, module2) {
|
|
10
|
+
"use strict";
|
|
11
|
+
var crypto = require("crypto");
|
|
12
|
+
var fs2 = require("fs");
|
|
13
|
+
var http = require("https");
|
|
14
|
+
var path = require("path");
|
|
15
|
+
var zlib = require("zlib");
|
|
16
|
+
async function download_http(url, dest) {
|
|
17
|
+
if (Array.isArray(url)) {
|
|
18
|
+
let urls = url;
|
|
19
|
+
for (let url2 of urls) {
|
|
20
|
+
try {
|
|
21
|
+
await download_http(url2, dest);
|
|
22
|
+
return;
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if (err.code != 404)
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
throw new Error("All URLs returned error 404");
|
|
29
|
+
}
|
|
30
|
+
console.log(">> Downloading " + url);
|
|
31
|
+
let [tmp_name, file] = open_temporary_stream(dest);
|
|
32
|
+
try {
|
|
33
|
+
await new Promise((resolve, reject) => {
|
|
34
|
+
let request = http.get(url, (response) => {
|
|
35
|
+
if (response.statusCode != 200) {
|
|
36
|
+
let err = new Error(`Download failed: ${response.statusMessage} [${response.statusCode}]`);
|
|
37
|
+
err.code = response.statusCode;
|
|
38
|
+
reject(err);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
response.pipe(file);
|
|
42
|
+
file.on("finish", () => file.close(() => {
|
|
43
|
+
try {
|
|
44
|
+
fs2.renameSync(file.path, dest);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if (err.code != "EBUSY")
|
|
47
|
+
reject(err);
|
|
48
|
+
}
|
|
49
|
+
resolve();
|
|
50
|
+
}));
|
|
51
|
+
});
|
|
52
|
+
request.on("error", reject);
|
|
53
|
+
file.on("error", reject);
|
|
54
|
+
});
|
|
55
|
+
} catch (err) {
|
|
56
|
+
file.close();
|
|
57
|
+
try {
|
|
58
|
+
fs2.unlinkSync(tmp_name);
|
|
59
|
+
} catch (err2) {
|
|
60
|
+
if (err2.code != "ENOENT")
|
|
61
|
+
throw err2;
|
|
62
|
+
}
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function open_temporary_stream(prefix) {
|
|
67
|
+
let buf = Buffer.allocUnsafe(4);
|
|
68
|
+
for (; ; ) {
|
|
69
|
+
try {
|
|
70
|
+
crypto.randomFillSync(buf);
|
|
71
|
+
let suffix = buf.toString("hex").padStart(8, "0");
|
|
72
|
+
let filename = `${prefix}.${suffix}`;
|
|
73
|
+
let file = fs2.createWriteStream(filename, { flags: "wx", mode: 420 });
|
|
74
|
+
return [filename, file];
|
|
75
|
+
} catch (err) {
|
|
76
|
+
if (err.code != "EEXIST")
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function extract_targz(filename, dest_dir, strip = 0) {
|
|
82
|
+
let reader = fs2.createReadStream(filename).pipe(zlib.createGunzip());
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
let header = null;
|
|
85
|
+
let extended = {};
|
|
86
|
+
reader.on("readable", () => {
|
|
87
|
+
try {
|
|
88
|
+
for (; ; ) {
|
|
89
|
+
if (header == null) {
|
|
90
|
+
let buf = reader.read(512);
|
|
91
|
+
if (buf == null)
|
|
92
|
+
break;
|
|
93
|
+
if (!buf[0])
|
|
94
|
+
continue;
|
|
95
|
+
header = {
|
|
96
|
+
filename: buf.toString("utf-8", 0, 100).replace(/\0/g, ""),
|
|
97
|
+
mode: parseInt(buf.toString("ascii", 100, 109), 8),
|
|
98
|
+
size: parseInt(buf.toString("ascii", 124, 137), 8),
|
|
99
|
+
type: String.fromCharCode(buf[156])
|
|
100
|
+
};
|
|
101
|
+
Object.assign(header, extended);
|
|
102
|
+
extended = {};
|
|
103
|
+
header.filename = header.filename.replace(/\\/g, "/");
|
|
104
|
+
if (!header.filename.length)
|
|
105
|
+
throw new Error(`Insecure empty filename inside TAR archive`);
|
|
106
|
+
if (path_is_absolute(header.filename[0]))
|
|
107
|
+
throw new Error(`Insecure filename starting with / inside TAR archive`);
|
|
108
|
+
if (path_has_dotdot(header.filename))
|
|
109
|
+
throw new Error(`Insecure filename containing '..' inside TAR archive`);
|
|
110
|
+
for (let i = 0; i < strip; i++)
|
|
111
|
+
header.filename = header.filename.substr(header.filename.indexOf("/") + 1);
|
|
112
|
+
}
|
|
113
|
+
let aligned = Math.floor((header.size + 511) / 512) * 512;
|
|
114
|
+
let data = header.size ? reader.read(aligned) : null;
|
|
115
|
+
if (data == null) {
|
|
116
|
+
if (header.size)
|
|
117
|
+
break;
|
|
118
|
+
data = Buffer.alloc(0);
|
|
119
|
+
}
|
|
120
|
+
data = data.subarray(0, header.size);
|
|
121
|
+
if (header.type == "0" || header.type == "7") {
|
|
122
|
+
let filename2 = dest_dir + "/" + header.filename;
|
|
123
|
+
let dirname = path.dirname(filename2);
|
|
124
|
+
fs2.mkdirSync(dirname, { recursive: true, mode: 493 });
|
|
125
|
+
fs2.writeFileSync(filename2, data, { mode: header.mode });
|
|
126
|
+
} else if (header.type == "5") {
|
|
127
|
+
let filename2 = dest_dir + "/" + header.filename;
|
|
128
|
+
fs2.mkdirSync(filename2, { recursive: true, mode: header.mode });
|
|
129
|
+
} else if (header.type == "L") {
|
|
130
|
+
extended.filename = data.toString("utf-8").replace(/\0/g, "");
|
|
131
|
+
} else if (header.type == "x") {
|
|
132
|
+
let str = data.toString("utf-8");
|
|
133
|
+
try {
|
|
134
|
+
while (str.length) {
|
|
135
|
+
let matches = str.match(/^([0-9]+) ([a-zA-Z0-9\._]+)=(.*)\n/);
|
|
136
|
+
let skip = parseInt(matches[1], 10);
|
|
137
|
+
let key = matches[2];
|
|
138
|
+
let value = matches[3];
|
|
139
|
+
switch (key) {
|
|
140
|
+
case "path":
|
|
141
|
+
{
|
|
142
|
+
extended.filename = value;
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
case "size":
|
|
146
|
+
{
|
|
147
|
+
extended.size = parseInt(value, 10);
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
str = str.substr(skip).trimStart();
|
|
152
|
+
}
|
|
153
|
+
} catch (err) {
|
|
154
|
+
throw new Error("Malformed PAX entry");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
header = null;
|
|
158
|
+
}
|
|
159
|
+
} catch (err) {
|
|
160
|
+
reject(err);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
reader.on("error", reject);
|
|
164
|
+
reader.on("end", resolve);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function path_is_absolute(path2) {
|
|
168
|
+
if (process.platform == "win32" && path2.match(/^[a-zA-Z]:/))
|
|
169
|
+
path2 = path2.substr(2);
|
|
170
|
+
return is_path_separator(path2[0]);
|
|
171
|
+
}
|
|
172
|
+
function path_has_dotdot(path2) {
|
|
173
|
+
let start = 0;
|
|
174
|
+
for (; ; ) {
|
|
175
|
+
let offset = path2.indexOf("..", start);
|
|
176
|
+
if (offset < 0)
|
|
177
|
+
break;
|
|
178
|
+
start = offset + 2;
|
|
179
|
+
if (offset && !is_path_separator(path2[offset - 1]))
|
|
180
|
+
continue;
|
|
181
|
+
if (offset + 2 < path2.length && !is_path_separator(path2[offset + 2]))
|
|
182
|
+
continue;
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
function is_path_separator(c) {
|
|
188
|
+
if (c == "/")
|
|
189
|
+
return true;
|
|
190
|
+
if (process.platform == "win32" && c == "\\")
|
|
191
|
+
return true;
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
function determine_arch2() {
|
|
195
|
+
let arch2 = process.arch;
|
|
196
|
+
if (arch2 == "riscv32" || arch2 == "riscv64") {
|
|
197
|
+
let buf = read_file_header(process.execPath, 512);
|
|
198
|
+
let header = decode_elf_header(buf);
|
|
199
|
+
let float_abi = (header.e_flags & 6) >> 1;
|
|
200
|
+
switch (float_abi) {
|
|
201
|
+
case 0:
|
|
202
|
+
{
|
|
203
|
+
arch2 += "sf";
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
case 1:
|
|
207
|
+
{
|
|
208
|
+
arch2 += "hf32";
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
case 2:
|
|
212
|
+
{
|
|
213
|
+
arch2 += "hf64";
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
case 3:
|
|
217
|
+
{
|
|
218
|
+
arch2 += "hf128";
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
} else if (arch2 == "arm") {
|
|
223
|
+
arch2 = "arm32";
|
|
224
|
+
let buf = read_file_header(process.execPath, 512);
|
|
225
|
+
let header = decode_elf_header(buf);
|
|
226
|
+
if (header.e_flags & 1024) {
|
|
227
|
+
arch2 += "hf";
|
|
228
|
+
} else if (header.e_flags & 512) {
|
|
229
|
+
arch2 += "sf";
|
|
230
|
+
} else {
|
|
231
|
+
throw new Error("Unknown ARM floating-point ABI");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return arch2;
|
|
235
|
+
}
|
|
236
|
+
function read_file_header(filename, read) {
|
|
237
|
+
let fd = null;
|
|
238
|
+
try {
|
|
239
|
+
let fd2 = fs2.openSync(filename);
|
|
240
|
+
let buf = Buffer.allocUnsafe(read);
|
|
241
|
+
let len = fs2.readSync(fd2, buf);
|
|
242
|
+
return buf.subarray(0, len);
|
|
243
|
+
} finally {
|
|
244
|
+
if (fd != null)
|
|
245
|
+
fs2.closeSync(fd);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function decode_elf_header(buf) {
|
|
249
|
+
let header = {};
|
|
250
|
+
if (buf.length < 16)
|
|
251
|
+
throw new Error("Truncated header");
|
|
252
|
+
if (buf[0] != 127 || buf[1] != 69 || buf[2] != 76 || buf[3] != 70)
|
|
253
|
+
throw new Error("Invalid magic number");
|
|
254
|
+
if (buf[6] != 1)
|
|
255
|
+
throw new Error("Invalid ELF version");
|
|
256
|
+
if (buf[5] != 1)
|
|
257
|
+
throw new Error("Big-endian architectures are not supported");
|
|
258
|
+
let machine = buf.readUInt16LE(18);
|
|
259
|
+
switch (machine) {
|
|
260
|
+
case 3:
|
|
261
|
+
{
|
|
262
|
+
header.e_machine = "ia32";
|
|
263
|
+
}
|
|
264
|
+
break;
|
|
265
|
+
case 40:
|
|
266
|
+
{
|
|
267
|
+
header.e_machine = "arm";
|
|
268
|
+
}
|
|
269
|
+
break;
|
|
270
|
+
case 62:
|
|
271
|
+
{
|
|
272
|
+
header.e_machine = "amd64";
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
275
|
+
case 183:
|
|
276
|
+
{
|
|
277
|
+
header.e_machine = "arm64";
|
|
278
|
+
}
|
|
279
|
+
break;
|
|
280
|
+
case 243:
|
|
281
|
+
{
|
|
282
|
+
switch (buf[4]) {
|
|
283
|
+
case 1:
|
|
284
|
+
{
|
|
285
|
+
header.e_machine = "riscv32";
|
|
286
|
+
}
|
|
287
|
+
break;
|
|
288
|
+
case 2:
|
|
289
|
+
{
|
|
290
|
+
header.e_machine = "riscv64";
|
|
291
|
+
}
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
break;
|
|
296
|
+
default:
|
|
297
|
+
throw new Error("Unknown ELF machine type");
|
|
298
|
+
}
|
|
299
|
+
switch (buf[4]) {
|
|
300
|
+
case 1:
|
|
301
|
+
{
|
|
302
|
+
buf = buf.subarray(0, 68);
|
|
303
|
+
if (buf.length < 68)
|
|
304
|
+
throw new Error("Truncated ELF header");
|
|
305
|
+
header.ei_class = 32;
|
|
306
|
+
header.e_flags = buf.readUInt32LE(36);
|
|
307
|
+
}
|
|
308
|
+
break;
|
|
309
|
+
case 2:
|
|
310
|
+
{
|
|
311
|
+
buf = buf.subarray(0, 120);
|
|
312
|
+
if (buf.length < 120)
|
|
313
|
+
throw new Error("Truncated ELF header");
|
|
314
|
+
header.ei_class = 64;
|
|
315
|
+
header.e_flags = buf.readUInt32LE(48);
|
|
316
|
+
}
|
|
317
|
+
break;
|
|
318
|
+
default:
|
|
319
|
+
throw new Error("Invalid ELF class");
|
|
320
|
+
}
|
|
321
|
+
return header;
|
|
322
|
+
}
|
|
323
|
+
function unlink_recursive(path2) {
|
|
324
|
+
try {
|
|
325
|
+
if (fs2.rmSync != null) {
|
|
326
|
+
fs2.rmSync(path2, { recursive: true, maxRetries: process.platform == "win32" ? 3 : 0 });
|
|
327
|
+
} else {
|
|
328
|
+
fs2.rmdirSync(path2, { recursive: true, maxRetries: process.platform == "win32" ? 3 : 0 });
|
|
329
|
+
}
|
|
330
|
+
} catch (err) {
|
|
331
|
+
if (err.code !== "ENOENT")
|
|
332
|
+
throw err;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function get_napi_version2(napi, major) {
|
|
336
|
+
if (napi > 8)
|
|
337
|
+
return null;
|
|
338
|
+
const support = {
|
|
339
|
+
6: ["6.14.2", "6.14.2", "6.14.2"],
|
|
340
|
+
8: ["8.6.0", "8.10.0", "8.11.2"],
|
|
341
|
+
9: ["9.0.0", "9.3.0", "9.11.0"],
|
|
342
|
+
10: ["10.0.0", "10.0.0", "10.0.0", "10.16.0", "10.17.0", "10.20.0", "10.23.0"],
|
|
343
|
+
11: ["11.0.0", "11.0.0", "11.0.0", "11.8.0"],
|
|
344
|
+
12: ["12.0.0", "12.0.0", "12.0.0", "12.0.0", "12.11.0", "12.17.0", "12.19.0", "12.22.0"],
|
|
345
|
+
13: ["13.0.0", "13.0.0", "13.0.0", "13.0.0", "13.0.0"],
|
|
346
|
+
14: ["14.0.0", "14.0.0", "14.0.0", "14.0.0", "14.0.0", "14.0.0", "14.12.0", "14.17.0"],
|
|
347
|
+
15: ["15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.0.0", "15.12.0"]
|
|
348
|
+
};
|
|
349
|
+
const max = Math.max(...Object.keys(support).map((k) => parseInt(k, 10)));
|
|
350
|
+
if (major > max)
|
|
351
|
+
return major + ".0.0";
|
|
352
|
+
if (support[major] == null)
|
|
353
|
+
return null;
|
|
354
|
+
let required = support[major][napi - 1] || null;
|
|
355
|
+
return required;
|
|
356
|
+
}
|
|
357
|
+
function cmp_version(ver1, ver2) {
|
|
358
|
+
ver1 = String(ver1).replace(/-.*$/, "").split(".").reduce((acc, v, idx) => acc + parseInt(v, 10) * Math.pow(10, 2 * (5 - idx)), 0);
|
|
359
|
+
ver2 = String(ver2).replace(/-.*$/, "").split(".").reduce((acc, v, idx) => acc + parseInt(v, 10) * Math.pow(10, 2 * (5 - idx)), 0);
|
|
360
|
+
let cmp = Math.min(Math.max(ver1 - ver2, -1), 1);
|
|
361
|
+
return cmp;
|
|
362
|
+
}
|
|
363
|
+
module2.exports = {
|
|
364
|
+
download_http,
|
|
365
|
+
extract_targz,
|
|
366
|
+
path_is_absolute,
|
|
367
|
+
path_has_dotdot,
|
|
368
|
+
determine_arch: determine_arch2,
|
|
369
|
+
unlink_recursive,
|
|
370
|
+
get_napi_version: get_napi_version2,
|
|
371
|
+
cmp_version
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
// build/dist/src/koffi/package.json
|
|
377
|
+
var require_package = __commonJS({
|
|
378
|
+
"build/dist/src/koffi/package.json"(exports2, module2) {
|
|
379
|
+
module2.exports = {
|
|
380
|
+
name: "koffi",
|
|
381
|
+
version: "2.6.2",
|
|
382
|
+
stable: "2.6.2",
|
|
383
|
+
description: "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
384
|
+
keywords: [
|
|
385
|
+
"foreign",
|
|
386
|
+
"function",
|
|
387
|
+
"interface",
|
|
388
|
+
"ffi",
|
|
389
|
+
"binding",
|
|
390
|
+
"c",
|
|
391
|
+
"napi"
|
|
392
|
+
],
|
|
393
|
+
repository: {
|
|
394
|
+
type: "git",
|
|
395
|
+
url: "https://github.com/Koromix/koffi"
|
|
396
|
+
},
|
|
397
|
+
homepage: "https://koffi.dev/",
|
|
398
|
+
author: {
|
|
399
|
+
name: "Niels Martign\xE8ne",
|
|
400
|
+
email: "niels.martignene@protonmail.com",
|
|
401
|
+
url: "https://koromix.dev/"
|
|
402
|
+
},
|
|
403
|
+
main: "./index.js",
|
|
404
|
+
types: "./index.d.ts",
|
|
405
|
+
scripts: {
|
|
406
|
+
test: "node tools/qemu.js test",
|
|
407
|
+
prepack: `echo 'Use "npm run prepare" instead' && false`,
|
|
408
|
+
prepublishOnly: `echo 'Use "npm run release" instead' && false`,
|
|
409
|
+
release: "node tools/qemu.js publish"
|
|
410
|
+
},
|
|
411
|
+
license: "MIT",
|
|
412
|
+
devDependencies: {
|
|
413
|
+
chalk: "^4.1.2",
|
|
414
|
+
esbuild: "^0.19.2",
|
|
415
|
+
"ffi-napi": "^4.0.3",
|
|
416
|
+
"ffi-rs": "^1.0.12",
|
|
417
|
+
minimatch: "^5.0.1",
|
|
418
|
+
"node-ssh": "^12.0.3",
|
|
419
|
+
raylib: "^0.9.2",
|
|
420
|
+
"ref-napi": "^3.0.3",
|
|
421
|
+
"ref-struct-di": "^1.1.1",
|
|
422
|
+
tar: "^6.1.11"
|
|
423
|
+
},
|
|
424
|
+
cnoke: {
|
|
425
|
+
output: "build/koffi/{{ platform }}_{{ arch }}",
|
|
426
|
+
napi: 8,
|
|
427
|
+
require: "./src/index.js"
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// build/dist/src/koffi/indirect.js
|
|
434
|
+
var util = require("util");
|
|
435
|
+
var fs = require("fs");
|
|
436
|
+
var { get_napi_version, determine_arch } = require_tools();
|
|
437
|
+
var pkg = require_package();
|
|
438
|
+
if (process.versions.napi == null || process.versions.napi < pkg.cnoke.napi) {
|
|
439
|
+
let major = parseInt(process.versions.node, 10);
|
|
440
|
+
let required = get_napi_version(pkg.cnoke.napi, major);
|
|
441
|
+
if (required != null) {
|
|
442
|
+
throw new Error(`Project ${pkg.name} requires Node >= ${required} in the Node ${major}.x branch (N-API >= ${pkg.cnoke.napi})`);
|
|
443
|
+
} else {
|
|
444
|
+
throw new Error(`Project ${pkg.name} does not support the Node ${major}.x branch (N-API < ${pkg.cnoke.napi})`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
var arch = determine_arch();
|
|
448
|
+
var triplet = `${process.platform}_${arch}`;
|
|
449
|
+
var native = null;
|
|
450
|
+
{
|
|
451
|
+
let names = [
|
|
452
|
+
`/build/koffi/${process.platform}_${arch}/koffi.node`,
|
|
453
|
+
`/koffi/${process.platform}_${arch}/koffi.node`,
|
|
454
|
+
`/node_modules/koffi/build/koffi/${process.platform}_${arch}/koffi.node`
|
|
455
|
+
];
|
|
456
|
+
for (let name of names) {
|
|
457
|
+
if (fs.existsSync(__dirname + name)) {
|
|
458
|
+
native = require(__dirname + name);
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (native == null && process.resourcesPath != null) {
|
|
463
|
+
for (let name of names) {
|
|
464
|
+
if (fs.existsSync(process.resourcesPath + name)) {
|
|
465
|
+
native = require(process.resourcesPath + name);
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (native == null)
|
|
472
|
+
throw new Error("Cannot find the native Koffi module; did you bundle it correctly?");
|
|
473
|
+
if (native.version != pkg.version)
|
|
474
|
+
throw new Error("Mismatched native Koffi modules");
|
|
475
|
+
module.exports = {
|
|
476
|
+
...native,
|
|
477
|
+
// Deprecated functions
|
|
478
|
+
handle: util.deprecate(native.opaque, "The koffi.handle() function was deprecated in Koffi 2.1, use koffi.opaque() instead", "KOFFI001"),
|
|
479
|
+
callback: util.deprecate(native.proto, "The koffi.callback() function was deprecated in Koffi 2.4, use koffi.proto() instead", "KOFFI002")
|
|
480
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koffi",
|
|
3
|
-
"version": "2.6.
|
|
4
|
-
"stable": "2.6.
|
|
3
|
+
"version": "2.6.2",
|
|
4
|
+
"stable": "2.6.2",
|
|
5
5
|
"description": "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"foreign",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"email": "niels.martignene@protonmail.com",
|
|
23
23
|
"url": "https://koromix.dev/"
|
|
24
24
|
},
|
|
25
|
-
"main": "
|
|
26
|
-
"types": "
|
|
25
|
+
"main": "./index.js",
|
|
26
|
+
"types": "./index.d.ts",
|
|
27
27
|
"scripts": {
|
|
28
28
|
"install": "node src/cnoke/cnoke.js -p . -d src/koffi --prebuild"
|
|
29
29
|
},
|
package/src/core/libcc/libcc.cc
CHANGED
|
@@ -3265,7 +3265,7 @@ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int
|
|
|
3265
3265
|
case (int)OpenFlag::Append: {
|
|
3266
3266
|
access = GENERIC_WRITE;
|
|
3267
3267
|
share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
3268
|
-
creation =
|
|
3268
|
+
creation = OPEN_ALWAYS;
|
|
3269
3269
|
attributes = FILE_ATTRIBUTE_NORMAL;
|
|
3270
3270
|
oflags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY | _O_NOINHERIT;
|
|
3271
3271
|
} break;
|
|
@@ -3293,7 +3293,15 @@ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int
|
|
|
3293
3293
|
}
|
|
3294
3294
|
share |= FILE_SHARE_DELETE;
|
|
3295
3295
|
|
|
3296
|
-
HANDLE h;
|
|
3296
|
+
HANDLE h = nullptr;
|
|
3297
|
+
int fd = -1;
|
|
3298
|
+
RG_DEFER_N(err_guard) {
|
|
3299
|
+
close(fd);
|
|
3300
|
+
if (h) {
|
|
3301
|
+
CloseHandle(h);
|
|
3302
|
+
}
|
|
3303
|
+
};
|
|
3304
|
+
|
|
3297
3305
|
if (win32_utf8) {
|
|
3298
3306
|
h = CreateFileA(filename, access, share, nullptr, creation, attributes, nullptr);
|
|
3299
3307
|
} else {
|
|
@@ -3321,15 +3329,20 @@ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int
|
|
|
3321
3329
|
return ret;
|
|
3322
3330
|
}
|
|
3323
3331
|
|
|
3324
|
-
|
|
3332
|
+
fd = _open_osfhandle((intptr_t)h, oflags);
|
|
3325
3333
|
if (fd < 0) {
|
|
3326
3334
|
LogError("Cannot open '%1': %2", filename, strerror(errno));
|
|
3327
|
-
|
|
3335
|
+
return OpenResult::OtherError;
|
|
3336
|
+
}
|
|
3328
3337
|
|
|
3338
|
+
if ((flags & (int)OpenFlag::Append) && _lseeki64(fd, 0, SEEK_END) < 0) {
|
|
3339
|
+
LogError("Cannot move file pointer: %1", strerror(errno));
|
|
3329
3340
|
return OpenResult::OtherError;
|
|
3330
3341
|
}
|
|
3331
3342
|
|
|
3343
|
+
err_guard.Disable();
|
|
3332
3344
|
*out_fd = fd;
|
|
3345
|
+
|
|
3333
3346
|
return OpenResult::Success;
|
|
3334
3347
|
}
|
|
3335
3348
|
|
|
@@ -4871,15 +4884,20 @@ const char *GetUserConfigPath(const char *name, Allocator *alloc)
|
|
|
4871
4884
|
const char *xdg = getenv("XDG_CONFIG_HOME");
|
|
4872
4885
|
const char *home = getenv("HOME");
|
|
4873
4886
|
|
|
4887
|
+
const char *path = nullptr;
|
|
4888
|
+
|
|
4874
4889
|
if (xdg) {
|
|
4875
|
-
|
|
4876
|
-
return path;
|
|
4890
|
+
path = Fmt(alloc, "%1%/%2", xdg, name).ptr;
|
|
4877
4891
|
} else if (home) {
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
return nullptr;
|
|
4892
|
+
path = Fmt(alloc, "%1%/.config/%2", home, name).ptr;
|
|
4893
|
+
} else if (!getuid()) {
|
|
4894
|
+
path = Fmt(alloc, "/root/.config/%1", name).ptr;
|
|
4882
4895
|
}
|
|
4896
|
+
|
|
4897
|
+
if (path && !EnsureDirectoryExists(path))
|
|
4898
|
+
return nullptr;
|
|
4899
|
+
|
|
4900
|
+
return path;
|
|
4883
4901
|
}
|
|
4884
4902
|
|
|
4885
4903
|
const char *GetUserCachePath(const char *name, Allocator *alloc)
|
|
@@ -4889,15 +4907,20 @@ const char *GetUserCachePath(const char *name, Allocator *alloc)
|
|
|
4889
4907
|
const char *xdg = getenv("XDG_CACHE_HOME");
|
|
4890
4908
|
const char *home = getenv("HOME");
|
|
4891
4909
|
|
|
4910
|
+
const char *path = nullptr;
|
|
4911
|
+
|
|
4892
4912
|
if (xdg) {
|
|
4893
|
-
|
|
4894
|
-
return path;
|
|
4913
|
+
path = Fmt(alloc, "%1%/%2", xdg, name).ptr;
|
|
4895
4914
|
} else if (home) {
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
return nullptr;
|
|
4915
|
+
path = Fmt(alloc, "%1%/.cache/%2", home, name).ptr;
|
|
4916
|
+
} else if (!getuid()) {
|
|
4917
|
+
path = Fmt(alloc, "/root/.cache/%1", name).ptr;
|
|
4900
4918
|
}
|
|
4919
|
+
|
|
4920
|
+
if (path && !EnsureDirectoryExists(path))
|
|
4921
|
+
return nullptr;
|
|
4922
|
+
|
|
4923
|
+
return path;
|
|
4901
4924
|
}
|
|
4902
4925
|
|
|
4903
4926
|
const char *GetSystemConfigPath(const char *name, Allocator *alloc)
|
|
@@ -5122,7 +5145,8 @@ static RG_THREAD_LOCAL Size rnd_offset;
|
|
|
5122
5145
|
|
|
5123
5146
|
static void InitChaCha20(uint32_t state[16], uint32_t key[8], uint32_t iv[2])
|
|
5124
5147
|
{
|
|
5125
|
-
static
|
|
5148
|
+
alignas(uint32_t) static char str[] = "expand 32-byte k";
|
|
5149
|
+
const uint32_t *magic = (const uint32_t *)str;
|
|
5126
5150
|
|
|
5127
5151
|
state[0] = LittleEndian(magic[0]);
|
|
5128
5152
|
state[1] = LittleEndian(magic[1]);
|
|
File without changes
|