1
+ /*
2
+ Copyright (c) Anthony Beaumont
3
+ This source code is licensed under the MIT License
4
+ found in the LICENSE file in the root directory of this source tree.
5
+ */
6
+
7
+ /*
8
+ ⚠️ Experimental and not yet tested
9
+ Based on https://github.com/nodejs/node/pull/46905
10
+ */
11
+
12
+ import { platform } from "node:process" ;
13
+ import { getNativeFunction } from "node:ffi" ;
14
+ import { Failure } from "@xan105/error" ;
15
+ import { asBoolean , asArray } from "@xan105/is/opt" ;
16
+ import {
17
+ shouldObj ,
18
+ shouldObjWithinObj ,
19
+ shouldStringNotEmpty
20
+ } from "@xan105/is/assert" ;
21
+
22
+ function load ( path , option = { } ) {
23
+
24
+ shouldStringNotEmpty ( path ) ;
25
+ shouldObj ( option ) ;
26
+
27
+ const options = {
28
+ ignoreLoadingFail : asBoolean ( option . ignoreLoadingFail ) ?? false ,
29
+ ignoreMissingSymbol : asBoolean ( option . ignoreMissingSymbol ) ?? false
30
+ } ;
31
+
32
+ const ext = {
33
+ "win32" : ".dll" ,
34
+ "darwin" : ".dylib" ,
35
+ } [ platform ] ?? ".so" ;
36
+
37
+ if ( path . indexOf ( ext ) === - 1 ) path += ext ;
38
+
39
+ const handle = function ( symbol , result , parameters ) {
40
+ try {
41
+ return getNativeFunction ( path , symbol , result , parameters ) ;
42
+ } catch ( err ) {
43
+ if ( err . code === "ERR_FFI_LIBRARY_LOAD_FAILED" && options . ignoreLoadingFail )
44
+ return undefined ;
45
+ else if ( err . code === "ERR_FFI_SYMBOL_NOT_FOUND" && options . ignoreMissingSymbol )
46
+ return undefined ;
47
+
48
+ throw new Failure ( err . message , {
49
+ code : "ERR_FFI" ,
50
+ cause : err ,
51
+ info : { lib : path , symbol }
52
+ } ) ;
53
+ }
54
+ } ;
55
+
56
+ return handle ;
57
+ }
58
+
59
+ function dlopen ( path , symbols , option ) {
60
+
61
+ shouldObjWithinObj ( symbols ) ;
62
+
63
+ const lib = Object . create ( null ) ;
64
+ const handle = load ( path , option ) ;
65
+
66
+ for ( const [ name , definition ] of Object . entries ( symbols ) ) {
67
+
68
+ if ( name === "__proto__" ) continue ; //not allowed
69
+
70
+ const parameters = asArray ( definition . parameters ) ?? [ ] ;
71
+ const result = definition . result || "void" ;
72
+ const nonblocking = asBoolean ( definition . nonblocking ) ?? false ;
73
+ const symbol = definition . symbol || name ;
74
+
75
+ const fn = handle ( symbol , result , parameters ) ;
76
+ if ( typeof fn === "function" ) lib [ name ] = fn ;
77
+ }
78
+
79
+ return lib ;
80
+ }
81
+
82
+ export { load , dlopen }
0 commit comments