koffi 2.5.13 → 2.5.15
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 +5 -1
- 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.exp +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.exp +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.exp +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/koffi-2.5.15.tgz +0 -0
- package/package.json +4 -4
- package/src/cnoke/assets/win_delay_hook.c +29 -12
- package/src/cnoke/cnoke.js +7 -0
- package/src/cnoke/src/builder.js +12 -30
- package/src/index.js +542 -87
- package/src/koffi/examples/nwjs/src/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
### Koffi 2.5
|
|
6
6
|
|
|
7
|
-
#### Koffi 2.5.
|
|
7
|
+
#### Koffi 2.5.15 (2023-08-24)
|
|
8
|
+
|
|
9
|
+
- Run Koffi tests through usual index.js entry point
|
|
10
|
+
|
|
11
|
+
#### Koffi 2.5.14 (2023-08-23)
|
|
8
12
|
|
|
9
13
|
- Fix DLL error when using Koffi from NW.js on Windows
|
|
10
14
|
- Simplify NW.js Koffi example
|
|
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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/koffi-2.5.15.tgz
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koffi",
|
|
3
|
-
"version": "2.5.
|
|
4
|
-
"stable": "2.5.
|
|
3
|
+
"version": "2.5.15",
|
|
4
|
+
"stable": "2.5.15",
|
|
5
5
|
"description": "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"foreign",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"cnoke": {
|
|
32
|
+
"output": "build/koffi/{{ platform }}_{{ arch }}",
|
|
32
33
|
"napi": 8,
|
|
33
|
-
"require": "./src/index.js"
|
|
34
|
-
"output": "build/{{version}}/{{platform}}_{{arch}}"
|
|
34
|
+
"require": "./src/index.js"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -29,24 +29,41 @@
|
|
|
29
29
|
#include <windows.h>
|
|
30
30
|
#include <delayimp.h>
|
|
31
31
|
|
|
32
|
+
static HMODULE node_dll;
|
|
33
|
+
static HMODULE nw_dll;
|
|
34
|
+
|
|
32
35
|
static FARPROC WINAPI self_exe_hook(unsigned int event, DelayLoadInfo *info)
|
|
33
36
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
return
|
|
37
|
+
if (event == dliStartProcessing) {
|
|
38
|
+
node_dll = GetModuleHandleA("node.dll");
|
|
39
|
+
nw_dll = GetModuleHandleA("nw.dll");
|
|
40
|
+
|
|
41
|
+
return NULL;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (event == dliNotePreGetProcAddress) {
|
|
45
|
+
if (node_dll) {
|
|
46
|
+
FARPROC ret = GetProcAddress(node_dll, info->dlp.szProcName);
|
|
47
|
+
if (ret)
|
|
48
|
+
return ret;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (nw_dll) {
|
|
52
|
+
FARPROC ret = GetProcAddress(nw_dll, info->dlp.szProcName);
|
|
53
|
+
if (ret)
|
|
54
|
+
return ret;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (event == dliNotePreLoadLibrary && _stricmp(info->szDll, "node.exe") != 0) {
|
|
59
|
+
if (!node_dll) {
|
|
60
|
+
node_dll = GetModuleHandleA(NULL);
|
|
46
61
|
}
|
|
62
|
+
return (FARPROC)node_dll;
|
|
47
63
|
}
|
|
48
64
|
|
|
49
65
|
return NULL;
|
|
50
66
|
}
|
|
51
67
|
|
|
52
68
|
const PfnDliHook __pfnDliNotifyHook2 = self_exe_hook;
|
|
69
|
+
const PfnDliHook __pfnDliFailureHook2 = self_exe_hook;
|
package/src/cnoke/cnoke.js
CHANGED
|
@@ -77,6 +77,11 @@ async function main() {
|
|
|
77
77
|
throw new Error(`Missing value for ${arg}`);
|
|
78
78
|
|
|
79
79
|
config.project_dir = fs.realpathSync(value);
|
|
80
|
+
} else if (arg == '-o' || arg == '--output') {
|
|
81
|
+
if (value == null)
|
|
82
|
+
throw new Error(`Missing value for ${arg}`);
|
|
83
|
+
|
|
84
|
+
config.output_directory = value;
|
|
80
85
|
} else if ((command == 'build' || command == 'configure') && (arg == '-v' || arg == '--runtime-version')) {
|
|
81
86
|
if (value == null)
|
|
82
87
|
throw new Error(`Missing value for ${arg}`);
|
|
@@ -150,6 +155,8 @@ Commands:
|
|
|
150
155
|
Options:
|
|
151
156
|
-d, --directory <DIR> Change project directory
|
|
152
157
|
(default: current working directory)
|
|
158
|
+
-O, --output <DIR> Change explicit output directory
|
|
159
|
+
(default: ./build)
|
|
153
160
|
|
|
154
161
|
-B, --config <CONFIG> Change build type: RelWithDebInfo, Debug, Release
|
|
155
162
|
(default: ${cnoke.DefaultOptions.mode})
|
package/src/cnoke/src/builder.js
CHANGED
|
@@ -36,7 +36,6 @@ function Builder(config = {}) {
|
|
|
36
36
|
|
|
37
37
|
let app_dir = config.app_dir;
|
|
38
38
|
let project_dir = config.project_dir;
|
|
39
|
-
let package_dir = null;
|
|
40
39
|
|
|
41
40
|
if (app_dir == null)
|
|
42
41
|
app_dir = __dirname.replace(/\\/g, '/') + '/..';
|
|
@@ -44,7 +43,6 @@ function Builder(config = {}) {
|
|
|
44
43
|
project_dir = process.cwd();
|
|
45
44
|
app_dir = app_dir.replace(/\\/g, '/');
|
|
46
45
|
project_dir = project_dir.replace(/\\/g, '/');
|
|
47
|
-
package_dir = find_parent_directory(project_dir, 'package.json');
|
|
48
46
|
|
|
49
47
|
let runtime_version = config.runtime_version;
|
|
50
48
|
let arch = config.arch;
|
|
@@ -70,14 +68,15 @@ function Builder(config = {}) {
|
|
|
70
68
|
let pkg = read_package_json();
|
|
71
69
|
|
|
72
70
|
if (pkg.cnoke.output != null) {
|
|
73
|
-
build_dir =
|
|
71
|
+
build_dir = pkg.cnoke.output;
|
|
74
72
|
|
|
75
73
|
if (!tools.path_is_absolute(build_dir))
|
|
76
|
-
build_dir =
|
|
74
|
+
build_dir = project_dir + '/' + build_dir;
|
|
77
75
|
} else {
|
|
78
76
|
build_dir = project_dir + '/build';
|
|
79
77
|
}
|
|
80
78
|
}
|
|
79
|
+
build_dir = expand_path(build_dir);
|
|
81
80
|
work_dir = build_dir + `/v${runtime_version}_${arch}`;
|
|
82
81
|
|
|
83
82
|
let cmake_bin = null;
|
|
@@ -286,7 +285,7 @@ function Builder(config = {}) {
|
|
|
286
285
|
archive_filename = url;
|
|
287
286
|
|
|
288
287
|
if (!tools.path_is_absolute(archive_filename))
|
|
289
|
-
archive_filename = path.join(
|
|
288
|
+
archive_filename = path.join(project_dir, archive_filename);
|
|
290
289
|
|
|
291
290
|
if (!fs.existsSync(archive_filename))
|
|
292
291
|
throw new Error('Cannot find local prebuilt archive');
|
|
@@ -303,7 +302,7 @@ function Builder(config = {}) {
|
|
|
303
302
|
let require_filename = expand_path(pkg.cnoke.require);
|
|
304
303
|
|
|
305
304
|
if (!tools.path_is_absolute(require_filename))
|
|
306
|
-
require_filename = path.join(
|
|
305
|
+
require_filename = path.join(project_dir, require_filename);
|
|
307
306
|
|
|
308
307
|
if (fs.existsSync(require_filename)) {
|
|
309
308
|
let proc = spawnSync(process.execPath, ['-e', 'require(process.argv[1])', require_filename]);
|
|
@@ -321,21 +320,6 @@ function Builder(config = {}) {
|
|
|
321
320
|
tools.unlink_recursive(build_dir);
|
|
322
321
|
};
|
|
323
322
|
|
|
324
|
-
function find_parent_directory(dirname, basename)
|
|
325
|
-
{
|
|
326
|
-
if (process.platform == 'win32')
|
|
327
|
-
dirname = dirname.replace(/\\/g, '/');
|
|
328
|
-
|
|
329
|
-
do {
|
|
330
|
-
if (fs.existsSync(dirname + '/' + basename))
|
|
331
|
-
return dirname;
|
|
332
|
-
|
|
333
|
-
dirname = path.dirname(dirname);
|
|
334
|
-
} while (!dirname.endsWith('/'));
|
|
335
|
-
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
323
|
function get_cache_directory() {
|
|
340
324
|
if (process.platform == 'win32') {
|
|
341
325
|
let cache_dir = process.env['APPDATA'];
|
|
@@ -420,14 +404,12 @@ function Builder(config = {}) {
|
|
|
420
404
|
function read_package_json() {
|
|
421
405
|
let pkg = {};
|
|
422
406
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
throw err;
|
|
430
|
-
}
|
|
407
|
+
try {
|
|
408
|
+
let json = fs.readFileSync(project_dir + '/package.json', { encoding: 'utf-8' });
|
|
409
|
+
pkg = JSON.parse(json);
|
|
410
|
+
} catch (err) {
|
|
411
|
+
if (err.code != 'ENOENT')
|
|
412
|
+
throw err;
|
|
431
413
|
}
|
|
432
414
|
|
|
433
415
|
if (pkg.cnoke == null)
|
|
@@ -437,7 +419,7 @@ function Builder(config = {}) {
|
|
|
437
419
|
}
|
|
438
420
|
|
|
439
421
|
function expand_path(str) {
|
|
440
|
-
let ret = str.replace(/{{([a-zA-Z_][a-zA-Z_0-9]*)}}/g, (match, p1) => {
|
|
422
|
+
let ret = str.replace(/{{ *([a-zA-Z_][a-zA-Z_0-9]*) *}}/g, (match, p1) => {
|
|
441
423
|
switch (p1) {
|
|
442
424
|
case 'version': {
|
|
443
425
|
let pkg = read_package_json();
|
package/src/index.js
CHANGED
|
@@ -1,103 +1,558 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
7
|
-
// Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
-
// subject to the following conditions:
|
|
9
|
-
//
|
|
10
|
-
// The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
// copies or substantial portions of the Software.
|
|
12
|
-
//
|
|
13
|
-
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
-
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
15
|
-
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
-
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
-
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
18
|
-
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
19
|
-
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
20
|
-
// OTHER DEALINGS IN THE SOFTWARE.
|
|
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
|
+
};
|
|
21
6
|
|
|
22
|
-
|
|
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
|
+
});
|
|
23
375
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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.5.15",
|
|
382
|
+
stable: "2.5.15",
|
|
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: "src/index.js",
|
|
404
|
+
types: "src/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
|
+
minimatch: "^5.0.1",
|
|
417
|
+
"node-ssh": "^12.0.3",
|
|
418
|
+
raylib: "^0.9.2",
|
|
419
|
+
"ref-napi": "^3.0.3",
|
|
420
|
+
"ref-struct-di": "^1.1.1",
|
|
421
|
+
tar: "^6.1.11"
|
|
422
|
+
},
|
|
423
|
+
cnoke: {
|
|
424
|
+
output: "build/koffi/{{ platform }}_{{ arch }}",
|
|
425
|
+
napi: 8,
|
|
426
|
+
require: "./src/index.js"
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
});
|
|
28
431
|
|
|
432
|
+
// build/dist/src/koffi/src/index.js
|
|
433
|
+
var util = require("util");
|
|
434
|
+
var fs = require("fs");
|
|
435
|
+
var { get_napi_version, determine_arch } = require_tools();
|
|
436
|
+
var pkg = require_package();
|
|
29
437
|
if (process.versions.napi == null || process.versions.napi < pkg.cnoke.napi) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
}
|
|
438
|
+
let major = parseInt(process.versions.node, 10);
|
|
439
|
+
let required = get_napi_version(pkg.cnoke.napi, major);
|
|
440
|
+
if (required != null) {
|
|
441
|
+
throw new Error(`Project ${pkg.name} requires Node >= ${required} in the Node ${major}.x branch (N-API >= ${pkg.cnoke.napi})`);
|
|
442
|
+
} else {
|
|
443
|
+
throw new Error(`Project ${pkg.name} does not support the Node ${major}.x branch (N-API < ${pkg.cnoke.napi})`);
|
|
444
|
+
}
|
|
38
445
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
let native = null;
|
|
44
|
-
|
|
45
|
-
// Try an explicit list with static strings to help bundlers
|
|
446
|
+
var arch = determine_arch();
|
|
447
|
+
var triplet = `${process.platform}_${arch}`;
|
|
448
|
+
var native = null;
|
|
46
449
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
450
|
+
switch (triplet) {
|
|
451
|
+
case "darwin_arm64":
|
|
452
|
+
{
|
|
453
|
+
native = require("../build/koffi/darwin_arm64/koffi.node");
|
|
454
|
+
}
|
|
455
|
+
break;
|
|
456
|
+
case "darwin_x64":
|
|
457
|
+
{
|
|
458
|
+
native = require("../build/koffi/darwin_x64/koffi.node");
|
|
459
|
+
}
|
|
460
|
+
break;
|
|
461
|
+
case "freebsd_arm64":
|
|
462
|
+
{
|
|
463
|
+
native = require("../build/koffi/freebsd_arm64/koffi.node");
|
|
464
|
+
}
|
|
465
|
+
break;
|
|
466
|
+
case "freebsd_ia32":
|
|
467
|
+
{
|
|
468
|
+
native = require("../build/koffi/freebsd_ia32/koffi.node");
|
|
469
|
+
}
|
|
470
|
+
break;
|
|
471
|
+
case "freebsd_x64":
|
|
472
|
+
{
|
|
473
|
+
native = require("../build/koffi/freebsd_x64/koffi.node");
|
|
474
|
+
}
|
|
475
|
+
break;
|
|
476
|
+
case "linux_arm32hf":
|
|
477
|
+
{
|
|
478
|
+
native = require("../build/koffi/linux_arm32hf/koffi.node");
|
|
479
|
+
}
|
|
480
|
+
break;
|
|
481
|
+
case "linux_arm64":
|
|
482
|
+
{
|
|
483
|
+
native = require("../build/koffi/linux_arm64/koffi.node");
|
|
484
|
+
}
|
|
485
|
+
break;
|
|
486
|
+
case "linux_ia32":
|
|
487
|
+
{
|
|
488
|
+
native = require("../build/koffi/linux_ia32/koffi.node");
|
|
489
|
+
}
|
|
490
|
+
break;
|
|
491
|
+
case "linux_riscv64hf64":
|
|
492
|
+
{
|
|
493
|
+
native = require("../build/koffi/linux_riscv64hf64/koffi.node");
|
|
494
|
+
}
|
|
495
|
+
break;
|
|
496
|
+
case "linux_x64":
|
|
497
|
+
{
|
|
498
|
+
native = require("../build/koffi/linux_x64/koffi.node");
|
|
499
|
+
}
|
|
500
|
+
break;
|
|
501
|
+
case "openbsd_ia32":
|
|
502
|
+
{
|
|
503
|
+
native = require("../build/koffi/openbsd_ia32/koffi.node");
|
|
504
|
+
}
|
|
505
|
+
break;
|
|
506
|
+
case "openbsd_x64":
|
|
507
|
+
{
|
|
508
|
+
native = require("../build/koffi/openbsd_x64/koffi.node");
|
|
509
|
+
}
|
|
510
|
+
break;
|
|
511
|
+
case "win32_arm64":
|
|
512
|
+
{
|
|
513
|
+
native = require("../build/koffi/win32_arm64/koffi.node");
|
|
514
|
+
}
|
|
515
|
+
break;
|
|
516
|
+
case "win32_ia32":
|
|
517
|
+
{
|
|
518
|
+
native = require("../build/koffi/win32_ia32/koffi.node");
|
|
519
|
+
}
|
|
520
|
+
break;
|
|
521
|
+
case "win32_x64":
|
|
522
|
+
{
|
|
523
|
+
native = require("../build/koffi/win32_x64/koffi.node");
|
|
524
|
+
}
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
64
527
|
} catch (err) {
|
|
65
|
-
// Go on!
|
|
66
528
|
}
|
|
67
|
-
|
|
68
|
-
// And now, search everywhere we know
|
|
69
529
|
if (native == null) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
530
|
+
let names = [
|
|
531
|
+
`/koffi/${process.platform}_${arch}/koffi.node`,
|
|
532
|
+
`/node_modules/koffi/build/koffi/${process.platform}_${arch}/koffi.node`
|
|
533
|
+
];
|
|
534
|
+
for (let name of names) {
|
|
535
|
+
if (fs.existsSync(__dirname + name)) {
|
|
536
|
+
native = require(__dirname + name);
|
|
537
|
+
break;
|
|
80
538
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
539
|
+
}
|
|
540
|
+
if (native == null && process.resourcesPath != null) {
|
|
541
|
+
for (let name of names) {
|
|
542
|
+
if (fs.existsSync(process.resourcesPath + name)) {
|
|
543
|
+
native = require(process.resourcesPath + name);
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
89
546
|
}
|
|
547
|
+
}
|
|
90
548
|
}
|
|
91
|
-
|
|
92
549
|
if (native == null)
|
|
93
|
-
|
|
550
|
+
throw new Error("Cannot find the native Koffi module; did you bundle it correctly?");
|
|
94
551
|
if (native.version != pkg.version)
|
|
95
|
-
|
|
96
|
-
|
|
552
|
+
throw new Error("Mismatched native Koffi modules");
|
|
97
553
|
module.exports = {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
callback: util.deprecate(native.proto, 'The koffi.callback() function was deprecated in Koffi 2.4, use koffi.proto() instead', 'KOFFI002')
|
|
554
|
+
...native,
|
|
555
|
+
// Deprecated functions
|
|
556
|
+
handle: util.deprecate(native.opaque, "The koffi.handle() function was deprecated in Koffi 2.1, use koffi.opaque() instead", "KOFFI001"),
|
|
557
|
+
callback: util.deprecate(native.proto, "The koffi.callback() function was deprecated in Koffi 2.4, use koffi.proto() instead", "KOFFI002")
|
|
103
558
|
};
|