Skip to content

Commit 02fdb93

Browse files
committed
fix: various improvements.
Signed-off-by: Paolo Insogna <[email protected]>
1 parent da7cdbf commit 02fdb93

37 files changed

Lines changed: 1704 additions & 818 deletions

configure.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2215,7 +2215,7 @@ def bundled_ffi_supported(os_name, target_arch):
22152215
'freebsd': {'arm', 'arm64', 'x64'},
22162216
'linux': {'arm', 'arm64', 'x64'},
22172217
'mac': {'arm64', 'x64'},
2218-
'win': {'arm', 'arm64', 'x64'},
2218+
'win': {'arm64', 'x64'},
22192219
}
22202220

22212221
if target_arch == 'x86':

deps/libffi/generate-headers.py

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/usr/bin/env python3
22

33
import argparse
4+
import os
5+
import platform
46
import sys
57
from pathlib import Path
68

@@ -156,7 +158,7 @@ def render_fficonfig(os_name, target_arch):
156158

157159
def generate_headers(output_dir, target_arch, os_name):
158160
base_dir = Path(__file__).resolve().parent
159-
output_dir = Path(output_dir)
161+
output_dir = Path(str(output_dir).strip().strip('"'))
160162
output_dir.mkdir(parents=True, exist_ok=True)
161163

162164
target, target_dir = get_target(os_name, target_arch)
@@ -175,15 +177,62 @@ def generate_headers(output_dir, target_arch, os_name):
175177
encoding='utf-8')
176178

177179

180+
def detect_os_name():
181+
if sys.platform.startswith('win'):
182+
return 'win'
183+
if sys.platform == 'darwin':
184+
return 'mac'
185+
if sys.platform.startswith('linux'):
186+
return 'linux'
187+
if sys.platform.startswith('freebsd'):
188+
return 'freebsd'
189+
raise ValueError(f'Unsupported host platform {sys.platform!r}')
190+
191+
192+
def detect_target_arch():
193+
candidates = [
194+
os.environ.get('TARGET_ARCH'),
195+
os.environ.get('npm_config_arch'),
196+
os.environ.get('VSCMD_ARG_TGT_ARCH'),
197+
os.environ.get('Platform'),
198+
os.environ.get('PROCESSOR_ARCHITECTURE'),
199+
platform.machine(),
200+
]
201+
202+
aliases = {
203+
'amd64': 'x64',
204+
'x86_64': 'x64',
205+
'x64': 'x64',
206+
'win32': 'x64',
207+
'i386': 'x86',
208+
'i686': 'x86',
209+
'x86': 'x86',
210+
'arm64': 'arm64',
211+
'aarch64': 'arm64',
212+
'arm': 'arm',
213+
}
214+
215+
for candidate in candidates:
216+
if not candidate:
217+
continue
218+
normalized = aliases.get(candidate.lower())
219+
if normalized is not None:
220+
return normalized
221+
222+
raise ValueError('Unable to determine target architecture for libffi headers')
223+
224+
178225
def main(argv=None):
179226
parser = argparse.ArgumentParser(description='Generate libffi headers')
180227
parser.add_argument('--output-dir', required=True)
181-
parser.add_argument('--target-arch', required=True)
182-
parser.add_argument('--os', required=True)
228+
parser.add_argument('--target-arch')
229+
parser.add_argument('--os')
183230
args = parser.parse_args(argv)
184231

185232
try:
186-
generate_headers(args.output_dir, args.target_arch, args.os)
233+
generate_headers(args.output_dir,
234+
args.target_arch or detect_target_arch(),
235+
args.os or detect_os_name())
187236
except Exception as exc: # pylint: disable=broad-except
188237
print(exc, file=sys.stderr)
189238
return 1

deps/libffi/libffi.gyp

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
'src/java_raw_api.c',
77
'src/prep_cif.c',
88
'src/raw_api.c',
9+
'src/tramp.c',
910
'src/types.c',
1011
],
1112
'libffi_defines%': [],
@@ -18,7 +19,6 @@
1819
'variables': {
1920
'libffi_arch_sources': [
2021
'src/x86/ffiw64.c',
21-
'src/x86/win64_intel.S',
2222
],
2323
'libffi_defines': [
2424
'LIBFFI_HIDE_BASIC_TYPES',
@@ -54,8 +54,10 @@
5454
['target_arch == "x64"', {
5555
'variables': {
5656
'libffi_arch_sources': [
57+
'src/x86/ffiw64.c',
5758
'src/x86/ffi64.c',
5859
'src/x86/unix64.S',
60+
'src/x86/win64.S',
5961
],
6062
},
6163
}],
@@ -82,8 +84,10 @@
8284
['target_arch == "x64"', {
8385
'variables': {
8486
'libffi_arch_sources': [
87+
'src/x86/ffiw64.c',
8588
'src/x86/ffi64.c',
8689
'src/x86/unix64.S',
90+
'src/x86/win64.S',
8791
],
8892
},
8993
}],
@@ -136,12 +140,50 @@
136140
'action': [
137141
'<(python)',
138142
'generate-headers.py',
139-
'--output-dir=<(INTERMEDIATE_DIR)',
140-
'--target-arch=<(target_arch)',
141-
'--os=<(OS)',
143+
'--output-dir',
144+
'<(INTERMEDIATE_DIR)',
142145
],
143146
},
144147
],
148+
'conditions': [
149+
['OS == "win" and target_arch == "x64"', {
150+
'actions': [
151+
{
152+
'action_name': 'preprocess_win64_intel_asm',
153+
'process_outputs_as_sources': 1,
154+
'inputs': [
155+
'preprocess_asm.py',
156+
'include/ffi_cfi.h',
157+
'src/x86/asmnames.h',
158+
'src/x86/win64_intel.S',
159+
'<(INTERMEDIATE_DIR)/ffi.h',
160+
'<(INTERMEDIATE_DIR)/fficonfig.h',
161+
],
162+
'outputs': [
163+
'<(INTERMEDIATE_DIR)/win64_intel.asm',
164+
],
165+
'action': [
166+
'<(python)',
167+
'preprocess_asm.py',
168+
'--input',
169+
'src/x86/win64_intel.S',
170+
'--output',
171+
'<@(_outputs)',
172+
'--include-dir',
173+
'include',
174+
'--include-dir',
175+
'src/x86',
176+
'--include-dir',
177+
'<(INTERMEDIATE_DIR)',
178+
'--define',
179+
'FFI_BUILDING',
180+
'--define',
181+
'LIBFFI_HIDE_BASIC_TYPES',
182+
],
183+
},
184+
],
185+
}],
186+
],
145187
'direct_dependent_settings': {
146188
'include_dirs': [
147189
'include',

deps/libffi/preprocess_asm.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
from pathlib import Path
6+
import shlex
7+
import shutil
8+
import subprocess
9+
import sys
10+
11+
12+
def split_command(value):
13+
if not value:
14+
return None
15+
value = value.strip()
16+
if not value:
17+
return None
18+
return shlex.split(value, posix=(os.name != 'nt'))
19+
20+
21+
def find_compiler():
22+
for var in ('CC', 'CXX'):
23+
command = split_command(os.environ.get(var))
24+
if command and shutil.which(command[0]):
25+
return command
26+
27+
for name in ('cl.exe', 'cl', 'clang-cl.exe', 'clang-cl', 'cc', 'clang', 'gcc'):
28+
path = shutil.which(name)
29+
if path:
30+
return [path]
31+
32+
raise RuntimeError('Unable to locate a compiler for preprocessing assembly')
33+
34+
35+
def preprocess(args):
36+
compiler = find_compiler()
37+
output = Path(args.output)
38+
output.parent.mkdir(parents=True, exist_ok=True)
39+
40+
if os.name == 'nt' and Path(compiler[0]).name.lower() in ('cl.exe', 'cl', 'clang-cl.exe', 'clang-cl'):
41+
command = compiler + ['/nologo', '/EP', '/TC']
42+
command += [f'/I{include_dir}' for include_dir in args.include_dir]
43+
command += [f'/D{define}' for define in args.define]
44+
command += [args.input]
45+
else:
46+
command = compiler + ['-E', '-P', '-x', 'c']
47+
command += [f'-I{include_dir}' for include_dir in args.include_dir]
48+
command += [f'-D{define}' for define in args.define]
49+
command += [args.input]
50+
51+
result = subprocess.run(command, capture_output=True, text=True)
52+
if result.returncode != 0:
53+
sys.stderr.write(result.stderr)
54+
raise RuntimeError(f'Preprocessing failed: {" ".join(command)}')
55+
56+
output.write_text(result.stdout, encoding='utf-8')
57+
58+
59+
def main(argv=None):
60+
parser = argparse.ArgumentParser(description='Preprocess libffi assembly source')
61+
parser.add_argument('--input', required=True)
62+
parser.add_argument('--output', required=True)
63+
parser.add_argument('--include-dir', action='append', default=[])
64+
parser.add_argument('--define', action='append', default=[])
65+
args = parser.parse_args(argv)
66+
67+
preprocess(args)
68+
return 0
69+
70+
71+
if __name__ == '__main__':
72+
raise SystemExit(main())

doc/api/cli.md

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ native addons by default.
111111
Attempts to do so will throw an `ERR_DLOPEN_DISABLED` unless the
112112
user explicitly passes the `--allow-addons` flag when starting Node.js.
113113

114-
Example:
114+
Example without `--allow-child-process`:
115115

116116
```cjs
117117
// Attempt to require an native addon
@@ -160,7 +160,7 @@ child process by default.
160160
Attempts to do so will throw an `ERR_ACCESS_DENIED` unless the
161161
user explicitly passes the `--allow-child-process` flag when starting Node.js.
162162

163-
Example:
163+
Example without `--allow-ffi`:
164164

165165
```js
166166
const childProcess = require('node:child_process');
@@ -213,7 +213,7 @@ const lib = new DynamicLibrary('mylib.so');
213213
```
214214

215215
```console
216-
$ node --permission --experimental-ffi --allow-fs-read=* index.js
216+
$ node --permission --experimental-ffi index.js
217217
Error: Access to this API has been restricted. Use --allow-ffi to manage permissions.
218218
at node:internal/main/run_main_module:17:47 {
219219
code: 'ERR_ACCESS_DENIED',
@@ -1982,16 +1982,6 @@ changes:
19821982
19831983
Legacy alias for [`--no-require-module`][].
19841984

1985-
### `--no-experimental-ffi`
1986-
1987-
<!-- YAML
1988-
added: REPLACEME
1989-
-->
1990-
1991-
Disable the experimental [`node:ffi`][] module.
1992-
1993-
This flag is only available in builds with FFI support.
1994-
19951985
### `--no-experimental-sqlite`
19961986

19971987
<!-- YAML
@@ -2215,7 +2205,7 @@ following permissions are restricted:
22152205
* Worker Threads - manageable through [`--allow-worker`][] flag
22162206
* WASI - manageable through [`--allow-wasi`][] flag
22172207
* Addons - manageable through [`--allow-addons`][] flag
2218-
* FFI - manageable through \[`--allow-ffi`]\[] flag
2208+
* FFI - manageable through [`--allow-ffi`](#--allow-ffi) flag
22192209

22202210
### `--permission-audit`
22212211

@@ -3696,7 +3686,6 @@ one is included in the list below.
36963686
* `--no-addons`
36973687
* `--no-async-context-frame`
36983688
* `--no-deprecation`
3699-
* `--no-experimental-ffi`
37003689
* `--no-experimental-global-navigator`
37013690
* `--no-experimental-repl-await`
37023691
* `--no-experimental-sqlite`

0 commit comments

Comments
 (0)