Skip to content

Commit 36f2bcd

Browse files
committed
fs: use bigint for windowsHandle option
Signed-off-by: PickBas <sayed.kirill@gmail.com>
1 parent 329b98f commit 36f2bcd

6 files changed

Lines changed: 35 additions & 24 deletions

File tree

doc/api/fs.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,7 +3003,7 @@ changes:
30033003
* `highWaterMark` {integer} **Default:** `64 * 1024`
30043004
* `fs` {Object|null} **Default:** `null`
30053005
* `signal` {AbortSignal|null} **Default:** `null`
3006-
* `windowsHandle` {integer} A raw Win32 `HANDLE` value to read from, in place
3006+
* `windowsHandle` {bigint} A raw Win32 `HANDLE` value to read from, in place
30073007
of `fd`. Windows only. **Default:** `null`
30083008
* Returns: {fs.ReadStream}
30093009
@@ -3148,7 +3148,7 @@ changes:
31483148
[`stream.getDefaultHighWaterMark()`][].
31493149
* `flush` {boolean} If `true`, the underlying file descriptor is flushed
31503150
prior to closing it. **Default:** `false`.
3151-
* `windowsHandle` {integer} A raw Win32 `HANDLE` value to write to, in place
3151+
* `windowsHandle` {bigint} A raw Win32 `HANDLE` value to write to, in place
31523152
of `fd`. Windows only. **Default:** `null`
31533153
* Returns: {fs.WriteStream}
31543154

lib/internal/fs/streams.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const {
2323
ERR_SYSTEM_ERROR,
2424
} = require('internal/errors').codes;
2525
const {
26+
isWindows,
2627
kEmptyObject,
2728
} = require('internal/util');
2829
const {
@@ -43,7 +44,6 @@ const {
4344
} = require('internal/fs/utils');
4445
const { Readable, Writable, finished } = require('stream');
4546
const { toPathIfFileURL } = require('internal/url');
46-
const { isWindows } = require('internal/util');
4747
const binding = internalBinding('fs');
4848
const { O_RDONLY, O_WRONLY } = internalBinding('constants').fs;
4949
const kIoDone = Symbol('kIoDone');
@@ -178,7 +178,10 @@ function importWindowsHandle(stream, options, flags) {
178178
// implementation cannot be combined with it.
179179
throw new ERR_METHOD_NOT_IMPLEMENTED('windowsHandle with fs');
180180
}
181-
validateInteger(options.windowsHandle, 'options.windowsHandle');
181+
if (typeof options.windowsHandle !== 'bigint') {
182+
throw new ERR_INVALID_ARG_TYPE('options.windowsHandle', 'bigint',
183+
options.windowsHandle);
184+
}
182185
stream[kFs] = fs;
183186
return binding.handleToFd(options.windowsHandle, flags);
184187
}

src/node_file.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4154,15 +4154,20 @@ InternalFieldInfoBase* BindingData::Serialize(int index) {
41544154
static void HandleToFd(const FunctionCallbackInfo<Value>& args) {
41554155
Environment* env = Environment::GetCurrent(args);
41564156
CHECK_GE(args.Length(), 1);
4157-
CHECK(args[0]->IsNumber());
4157+
CHECK(args[0]->IsBigInt());
41584158

41594159
int flags = 0;
41604160
if (args[1]->IsNumber()) {
41614161
flags = args[1].As<Int32>()->Value();
41624162
}
41634163

4164-
intptr_t value =
4165-
static_cast<intptr_t>(args[0].As<Number>()->Value());
4164+
bool lossless;
4165+
int64_t handle = args[0].As<BigInt>()->Int64Value(&lossless);
4166+
if (!lossless) {
4167+
return THROW_ERR_OUT_OF_RANGE(env,
4168+
"windowsHandle does not fit into 64 bits");
4169+
}
4170+
intptr_t value = static_cast<intptr_t>(handle);
41664171

41674172
int fd = _open_osfhandle(value, flags);
41684173
if (fd == -1) {

test/addons/fs-windows-handle/binding.cc

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77

88
namespace {
99

10+
using v8::BigInt;
1011
using v8::Context;
1112
using v8::FunctionCallbackInfo;
1213
using v8::Isolate;
1314
using v8::Local;
14-
using v8::Number;
1515
using v8::Object;
1616
using v8::String;
1717
using v8::Value;
1818

1919
// Creates an anonymous pipe and returns its raw Win32 read/write HANDLE values
20-
// as JS numbers. These are NOT CRT file descriptors, so passing them as the
20+
// as JS bigints. These are NOT CRT file descriptors, so passing them as the
2121
// `windowsHandle` stream option exercises the HANDLE -> fd conversion path on
2222
// Windows. Returns undefined on other platforms.
2323
void CreatePipeHandles(const FunctionCallbackInfo<Value>& args) {
@@ -37,16 +37,16 @@ void CreatePipeHandles(const FunctionCallbackInfo<Value>& args) {
3737
result
3838
->Set(context,
3939
String::NewFromUtf8(isolate, "readHandle").ToLocalChecked(),
40-
Number::New(isolate,
41-
static_cast<double>(
42-
reinterpret_cast<intptr_t>(read_handle))))
40+
BigInt::New(
41+
isolate,
42+
static_cast<int64_t>(reinterpret_cast<intptr_t>(read_handle))))
4343
.Check();
4444
result
4545
->Set(context,
4646
String::NewFromUtf8(isolate, "writeHandle").ToLocalChecked(),
47-
Number::New(isolate,
48-
static_cast<double>(
49-
reinterpret_cast<intptr_t>(write_handle))))
47+
BigInt::New(
48+
isolate,
49+
static_cast<int64_t>(reinterpret_cast<intptr_t>(write_handle))))
5050
.Check();
5151
args.GetReturnValue().Set(result);
5252
#else
@@ -56,9 +56,7 @@ void CreatePipeHandles(const FunctionCallbackInfo<Value>& args) {
5656

5757
} // anonymous namespace
5858

59-
extern "C" NODE_MODULE_EXPORT void
60-
NODE_MODULE_INITIALIZER(Local<Object> exports,
61-
Local<Value> module,
62-
Local<Context> context) {
59+
extern "C" NODE_MODULE_EXPORT void NODE_MODULE_INITIALIZER(
60+
Local<Object> exports, Local<Value> module, Local<Context> context) {
6361
NODE_SET_METHOD(exports, "createPipeHandles", CreatePipeHandles);
6462
}

test/addons/fs-windows-handle/test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ const fs = require('fs');
1717
const binding = require(`./build/${common.buildType}/binding`);
1818

1919
const { readHandle, writeHandle } = binding.createPipeHandles();
20-
assert.strictEqual(typeof readHandle, 'number');
21-
assert.strictEqual(typeof writeHandle, 'number');
20+
assert.strictEqual(typeof readHandle, 'bigint');
21+
assert.strictEqual(typeof writeHandle, 'bigint');
2222

2323
const payload = 'payload';
2424

test/parallel/test-fs-stream-windows-handle.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const common = require('../common');
99
const assert = require('assert');
1010
const fs = require('fs');
1111

12-
const handle = 1;
12+
const handle = 1n;
1313

1414
for (const create of [fs.createReadStream, fs.createWriteStream]) {
1515
assert.throws(() => create(null, { windowsHandle: handle, fd: 2 }), {
@@ -32,11 +32,16 @@ for (const create of [fs.createReadStream, fs.createWriteStream]) {
3232
code: 'ERR_METHOD_NOT_IMPLEMENTED',
3333
});
3434

35-
// Must be an integer.
35+
// Must be a bigint.
3636
assert.throws(() => create(null, { windowsHandle: 'nope' }), {
3737
code: 'ERR_INVALID_ARG_TYPE',
3838
});
39-
assert.throws(() => create(null, { windowsHandle: 1.5 }), {
39+
assert.throws(() => create(null, { windowsHandle: 1 }), {
40+
code: 'ERR_INVALID_ARG_TYPE',
41+
});
42+
43+
// Must fit into 64 bits.
44+
assert.throws(() => create(null, { windowsHandle: 2n ** 64n }), {
4045
code: 'ERR_OUT_OF_RANGE',
4146
});
4247
}

0 commit comments

Comments
 (0)