koffi 2.6.11 → 2.7.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.
- package/CHANGELOG.md +12 -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/callbacks.md +19 -0
- package/doc/functions.md +15 -7
- package/doc/start.md +2 -2
- package/index.d.ts +11 -11
- package/index.js +11 -2
- package/indirect.js +11 -2
- package/package.json +2 -2
- package/src/core/libcc/libcc.cc +73 -6
- package/src/core/libcc/libcc.hh +10 -2
- package/src/core/libcc/mimetypes.inc +1228 -0
- package/src/core/libcc/mimetypes_gen.py +77 -0
- package/src/koffi/src/ffi.cc +40 -34
- package/src/koffi/src/ffi.hh +3 -0
- package/src/koffi/src/parser.cc +1 -9
- package/src/koffi/src/util.cc +21 -0
- package/src/koffi/src/util.hh +2 -0
- package/build/koffi/win32_x64/koffi.pdb +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright 2023 Niels Martignène <niels.martignene@protonmail.com>
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
# this software and associated documentation files (the “Software”), to deal in
|
|
7
|
+
# the Software without restriction, including without limitation the rights to use,
|
|
8
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
9
|
+
# Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
# subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
# This script uses the database of mimetypes distributed here: https://github.com/jshttp/mime-db
|
|
25
|
+
# to produce the X-header file mimetypes.inc
|
|
26
|
+
|
|
27
|
+
import os
|
|
28
|
+
import argparse
|
|
29
|
+
import json
|
|
30
|
+
|
|
31
|
+
if __name__ == "__main__":
|
|
32
|
+
parser = argparse.ArgumentParser(description = 'Update mimetypes include file')
|
|
33
|
+
parser.add_argument('-O', '--output_file', dest = 'output_file', action = 'store', help = 'Output file')
|
|
34
|
+
parser.add_argument('json', help = 'Source JSON database')
|
|
35
|
+
args = parser.parse_args()
|
|
36
|
+
|
|
37
|
+
if args.output_file is None:
|
|
38
|
+
output_file = os.path.join(os.path.dirname(__file__), 'mimetypes.inc')
|
|
39
|
+
else:
|
|
40
|
+
output_file = args.output_file
|
|
41
|
+
|
|
42
|
+
with open(args.json) as f:
|
|
43
|
+
db = json.load(f)
|
|
44
|
+
|
|
45
|
+
extensions = {}
|
|
46
|
+
for (k, v) in db.items():
|
|
47
|
+
if 'extensions' not in v:
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
for ext in v['extensions']:
|
|
51
|
+
if not ext in extensions:
|
|
52
|
+
extensions[ext] = 'application/x-'
|
|
53
|
+
if extensions[ext].startswith('application/x-'):
|
|
54
|
+
extensions[ext] = k
|
|
55
|
+
|
|
56
|
+
extensions = [(k, extensions[k]) for k in sorted(extensions.keys())]
|
|
57
|
+
extensions.sort()
|
|
58
|
+
|
|
59
|
+
with open(output_file) as f:
|
|
60
|
+
lines = f.readlines()
|
|
61
|
+
with open(output_file, 'w') as f:
|
|
62
|
+
for line in lines:
|
|
63
|
+
if not line.startswith('//'):
|
|
64
|
+
break
|
|
65
|
+
f.write(line)
|
|
66
|
+
|
|
67
|
+
print('', file = f)
|
|
68
|
+
print('#ifndef MIMETYPE', file = f)
|
|
69
|
+
print(' #error Please define MIMETYPE() before including mimetypes.inc', file = f)
|
|
70
|
+
print('#endif', file = f)
|
|
71
|
+
print('', file = f)
|
|
72
|
+
|
|
73
|
+
for k, v in extensions:
|
|
74
|
+
print(f'MIMETYPE(".{k}", "{v}")', file = f)
|
|
75
|
+
|
|
76
|
+
print('', file = f)
|
|
77
|
+
print('#undef MIMETYPE', file = f)
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -880,35 +880,50 @@ static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
|
|
|
880
880
|
return WrapType(env, instance, type);
|
|
881
881
|
}
|
|
882
882
|
|
|
883
|
-
static bool ParseClassicFunction(
|
|
884
|
-
Napi::Array parameters, FunctionInfo *func)
|
|
883
|
+
static bool ParseClassicFunction(const Napi::CallbackInfo &info, FunctionInfo *out_func)
|
|
885
884
|
{
|
|
885
|
+
Napi::Env env = info.Env();
|
|
886
886
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
887
887
|
|
|
888
|
+
Napi::String name = info[0u].As<Napi::String>();
|
|
889
|
+
Napi::Value ret = info[1u];
|
|
890
|
+
Napi::Array parameters = info[2u].As<Napi::Array>();
|
|
891
|
+
|
|
892
|
+
// Detect optional call convention
|
|
893
|
+
if (name.IsString() && DetectCallConvention(name.Utf8Value().c_str(), &out_func->convention)) {
|
|
894
|
+
if (info.Length() < 4) {
|
|
895
|
+
ThrowError<Napi::TypeError>(env, "Expected 4 arguments, got %1", info.Length());
|
|
896
|
+
return false;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
name = info[1u].As<Napi::String>();
|
|
900
|
+
ret = info[2u];
|
|
901
|
+
parameters = info[3u].As<Napi::Array>();
|
|
902
|
+
}
|
|
903
|
+
|
|
888
904
|
#ifdef _WIN32
|
|
889
|
-
if (
|
|
890
|
-
|
|
891
|
-
|
|
905
|
+
if (name.IsNumber()) {
|
|
906
|
+
out_func->ordinal_name = name.As<Napi::Number>().Int32Value();
|
|
907
|
+
name = name.ToString();
|
|
892
908
|
}
|
|
893
|
-
#
|
|
909
|
+
#endif
|
|
894
910
|
if (!name.IsString()) {
|
|
895
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, name));
|
|
911
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string or integer", GetValueType(instance, name));
|
|
896
912
|
return false;
|
|
897
913
|
}
|
|
898
|
-
#endif
|
|
899
914
|
|
|
900
|
-
|
|
915
|
+
out_func->name = DuplicateString(name.ToString().Utf8Value().c_str(), &instance->str_alloc).ptr;
|
|
901
916
|
|
|
902
|
-
|
|
903
|
-
if (!
|
|
917
|
+
out_func->ret.type = ResolveType(ret);
|
|
918
|
+
if (!out_func->ret.type)
|
|
904
919
|
return false;
|
|
905
|
-
if (!CanReturnType(
|
|
906
|
-
ThrowError<Napi::TypeError>(env, "You are not allowed to directly return %1 values (maybe try %1 *)",
|
|
920
|
+
if (!CanReturnType(out_func->ret.type)) {
|
|
921
|
+
ThrowError<Napi::TypeError>(env, "You are not allowed to directly return %1 values (maybe try %1 *)", out_func->ret.type->name);
|
|
907
922
|
return false;
|
|
908
923
|
}
|
|
909
924
|
|
|
910
925
|
if (!parameters.IsArray()) {
|
|
911
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for parameters of '%2', expected an array", GetValueType(instance, parameters),
|
|
926
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for parameters of '%2', expected an array", GetValueType(instance, parameters), out_func->name);
|
|
912
927
|
return false;
|
|
913
928
|
}
|
|
914
929
|
|
|
@@ -918,7 +933,7 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
|
|
|
918
933
|
Napi::String str = parameters.Get(parameters_len - 1).As<Napi::String>();
|
|
919
934
|
|
|
920
935
|
if (str.IsString() && str.Utf8Value() == "...") {
|
|
921
|
-
|
|
936
|
+
out_func->variadic = true;
|
|
922
937
|
parameters_len--;
|
|
923
938
|
}
|
|
924
939
|
}
|
|
@@ -934,21 +949,21 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
|
|
|
934
949
|
ThrowError<Napi::TypeError>(env, "Type %1 cannot be used as a parameter", param.type->name);
|
|
935
950
|
return false;
|
|
936
951
|
}
|
|
937
|
-
if (
|
|
952
|
+
if (out_func->parameters.len >= MaxParameters) {
|
|
938
953
|
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 parameters", MaxParameters);
|
|
939
954
|
return false;
|
|
940
955
|
}
|
|
941
|
-
if ((param.directions & 2) && ++
|
|
956
|
+
if ((param.directions & 2) && ++out_func->out_parameters >= MaxParameters) {
|
|
942
957
|
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 output parameters", MaxParameters);
|
|
943
958
|
return false;
|
|
944
959
|
}
|
|
945
960
|
|
|
946
961
|
param.offset = (int8_t)j;
|
|
947
962
|
|
|
948
|
-
|
|
963
|
+
out_func->parameters.Append(param);
|
|
949
964
|
}
|
|
950
965
|
|
|
951
|
-
|
|
966
|
+
out_func->required_parameters = (int8_t)out_func->parameters.len;
|
|
952
967
|
|
|
953
968
|
return true;
|
|
954
969
|
}
|
|
@@ -962,7 +977,7 @@ static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
|
|
|
962
977
|
RG_DEFER_N(err_guard) { instance->callbacks.RemoveLast(1); };
|
|
963
978
|
|
|
964
979
|
if (info.Length() >= 3) {
|
|
965
|
-
if (!ParseClassicFunction(
|
|
980
|
+
if (!ParseClassicFunction(info, func))
|
|
966
981
|
return env.Null();
|
|
967
982
|
} else if (info.Length() >= 1) {
|
|
968
983
|
if (!info[0].IsString()) {
|
|
@@ -1519,7 +1534,7 @@ extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, Bac
|
|
|
1519
1534
|
}
|
|
1520
1535
|
}
|
|
1521
1536
|
|
|
1522
|
-
static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info
|
|
1537
|
+
static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info)
|
|
1523
1538
|
{
|
|
1524
1539
|
Napi::Env env = info.Env();
|
|
1525
1540
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
@@ -1529,10 +1544,9 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
|
|
|
1529
1544
|
RG_DEFER { func->Unref(); };
|
|
1530
1545
|
|
|
1531
1546
|
func->lib = lib->Ref();
|
|
1532
|
-
func->convention = convention;
|
|
1533
1547
|
|
|
1534
1548
|
if (info.Length() >= 3) {
|
|
1535
|
-
if (!ParseClassicFunction(
|
|
1549
|
+
if (!ParseClassicFunction(info, func))
|
|
1536
1550
|
return env.Null();
|
|
1537
1551
|
} else if (info.Length() >= 1) {
|
|
1538
1552
|
if (!info[0].IsString()) {
|
|
@@ -1562,7 +1576,7 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
|
|
|
1562
1576
|
}
|
|
1563
1577
|
|
|
1564
1578
|
#ifdef _WIN32
|
|
1565
|
-
if (
|
|
1579
|
+
if (func->ordinal_name < 0) {
|
|
1566
1580
|
if (func->decorated_name) {
|
|
1567
1581
|
func->native = (void *)GetProcAddress((HMODULE)lib->module, func->decorated_name);
|
|
1568
1582
|
}
|
|
@@ -1570,7 +1584,7 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
|
|
|
1570
1584
|
func->native = (void *)GetProcAddress((HMODULE)lib->module, func->name);
|
|
1571
1585
|
}
|
|
1572
1586
|
} else {
|
|
1573
|
-
uint16_t ordinal = (uint16_t)
|
|
1587
|
+
uint16_t ordinal = (uint16_t)func->ordinal_name;
|
|
1574
1588
|
|
|
1575
1589
|
func->decorated_name = nullptr;
|
|
1576
1590
|
func->native = (void *)GetProcAddress((HMODULE)lib->module, (LPCSTR)(size_t)ordinal);
|
|
@@ -1720,20 +1734,13 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
|
|
|
1720
1734
|
func.AddFinalizer([](Napi::Env, LibraryHolder *lib) { lib->Unref(); }, lib); \
|
|
1721
1735
|
obj.Set((Name), func); \
|
|
1722
1736
|
} while (false)
|
|
1723
|
-
#define ADD_CONVENTION(Name, Value) ADD_METHOD((Name), FindLibraryFunction(info, Value))
|
|
1724
|
-
|
|
1725
|
-
ADD_CONVENTION("func", CallConvention::Cdecl);
|
|
1726
|
-
ADD_CONVENTION("cdecl", CallConvention::Cdecl);
|
|
1727
|
-
ADD_CONVENTION("stdcall", CallConvention::Stdcall);
|
|
1728
|
-
ADD_CONVENTION("fastcall", CallConvention::Fastcall);
|
|
1729
|
-
ADD_CONVENTION("thiscall", CallConvention::Thiscall);
|
|
1730
1737
|
|
|
1738
|
+
ADD_METHOD("func", FindLibraryFunction(info));
|
|
1731
1739
|
ADD_METHOD("symbol", FindSymbol(info));
|
|
1732
1740
|
|
|
1733
1741
|
// We can't unref the library after unload, obviously
|
|
1734
1742
|
obj.Set("unload", Napi::Function::New(env, UnloadLibrary, "unload", (void *)lib->Ref()));
|
|
1735
1743
|
|
|
1736
|
-
#undef ADD_CONVENTION
|
|
1737
1744
|
#undef ADD_METHOD
|
|
1738
1745
|
|
|
1739
1746
|
return obj;
|
|
@@ -2326,7 +2333,6 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
|
|
|
2326
2333
|
Napi::Object types = InitBaseTypes(env);
|
|
2327
2334
|
exports.Set("types", types);
|
|
2328
2335
|
|
|
2329
|
-
exports.Set("internal", Napi::Boolean::New(env, false));
|
|
2330
2336
|
exports.Set("version", Napi::String::New(env, RG_STRINGIFY(VERSION)));
|
|
2331
2337
|
|
|
2332
2338
|
return exports;
|
package/src/koffi/src/ffi.hh
CHANGED
package/src/koffi/src/parser.cc
CHANGED
|
@@ -40,15 +40,7 @@ bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
|
|
|
40
40
|
MarkError("You are not allowed to directly return %1 values (maybe try %1 *)", out_func->ret.type->name);
|
|
41
41
|
return false;
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
out_func->convention = CallConvention::Cdecl;
|
|
45
|
-
} else if (Match("__stdcall")) {
|
|
46
|
-
out_func->convention = CallConvention::Stdcall;
|
|
47
|
-
} else if (Match("__fastcall")) {
|
|
48
|
-
out_func->convention = CallConvention::Fastcall;
|
|
49
|
-
} else if (Match("__thiscall")) {
|
|
50
|
-
out_func->convention = CallConvention::Thiscall;
|
|
51
|
-
}
|
|
43
|
+
offset += (offset < tokens.len && DetectCallConvention(tokens[offset], &out_func->convention));
|
|
52
44
|
out_func->name = ParseIdentifier();
|
|
53
45
|
|
|
54
46
|
Consume("(");
|
package/src/koffi/src/util.cc
CHANGED
|
@@ -139,6 +139,8 @@ const TypeInfo *ResolveType(Napi::Value value, int *out_directions)
|
|
|
139
139
|
bucket->key = DuplicateString(str.c_str(), &instance->str_alloc).ptr;
|
|
140
140
|
bucket->value = type;
|
|
141
141
|
}
|
|
142
|
+
} else if (out_directions) {
|
|
143
|
+
*out_directions = 1;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
146
|
return type;
|
|
@@ -1506,6 +1508,25 @@ Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
|
|
|
1506
1508
|
return wrapper;
|
|
1507
1509
|
}
|
|
1508
1510
|
|
|
1511
|
+
bool DetectCallConvention(Span<const char> name, CallConvention *out_convention)
|
|
1512
|
+
{
|
|
1513
|
+
if (name == "__cdecl") {
|
|
1514
|
+
*out_convention = CallConvention::Cdecl;
|
|
1515
|
+
return true;
|
|
1516
|
+
} else if (name == "__stdcall") {
|
|
1517
|
+
*out_convention = CallConvention::Stdcall;
|
|
1518
|
+
return true;
|
|
1519
|
+
} else if (name == "__fastcall") {
|
|
1520
|
+
*out_convention = CallConvention::Fastcall;
|
|
1521
|
+
return true;
|
|
1522
|
+
} else if (name == "__thiscall") {
|
|
1523
|
+
*out_convention = CallConvention::Thiscall;
|
|
1524
|
+
return true;
|
|
1525
|
+
} else {
|
|
1526
|
+
return false;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1509
1530
|
static int AnalyseFlatRec(const TypeInfo *type, int offset, int count, FunctionRef<void(const TypeInfo *type, int offset, int count)> func)
|
|
1510
1531
|
{
|
|
1511
1532
|
if (type->primitive == PrimitiveKind::Record) {
|
package/src/koffi/src/util.hh
CHANGED
|
@@ -208,6 +208,8 @@ static inline Napi::Array GetOwnPropertyNames(Napi::Object obj)
|
|
|
208
208
|
|
|
209
209
|
Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func);
|
|
210
210
|
|
|
211
|
+
bool DetectCallConvention(Span<const char> name, CallConvention *out_convention);
|
|
212
|
+
|
|
211
213
|
int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
|
|
212
214
|
|
|
213
215
|
void DumpMemory(const char *type, Span<const uint8_t> bytes);
|
|
Binary file
|