Skip to content

Commit 2ca227f

Browse files
committed
fs: refactor FSReqWrap and After
Separate FSReqWrap definition into a new node_file.h. Add Reject and Resolve methods to encapsulate the callbacks and make the constructor, destructor protected instead of private in preparation to make FSReqWrap subclassable for the Promises implementation. Rework and simplify the After function slightly in preparation for a refactor. Introduce the node::fs namespace instead of using an anonymous namespace for fs methods. PR-URL: #17689 Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 0babd18 commit 2ca227f

File tree

3 files changed

+185
-144
lines changed

3 files changed

+185
-144
lines changed

node.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@
261261
'src/node_buffer.h',
262262
'src/node_constants.h',
263263
'src/node_debug_options.h',
264+
'src/node_file.h',
264265
'src/node_http2.h',
265266
'src/node_http2_state.h',
266267
'src/node_internals.h',

src/node_file.cc

Lines changed: 82 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "node_buffer.h"
2323
#include "node_internals.h"
2424
#include "node_stat_watcher.h"
25+
#include "node_file.h"
2526

2627
#include "req_wrap-inl.h"
2728
#include "string_bytes.h"
@@ -41,7 +42,42 @@
4142
#include <vector>
4243

4344
namespace node {
44-
namespace {
45+
46+
void FillStatsArray(double* fields, const uv_stat_t* s) {
47+
fields[0] = s->st_dev;
48+
fields[1] = s->st_mode;
49+
fields[2] = s->st_nlink;
50+
fields[3] = s->st_uid;
51+
fields[4] = s->st_gid;
52+
fields[5] = s->st_rdev;
53+
#if defined(__POSIX__)
54+
fields[6] = s->st_blksize;
55+
#else
56+
fields[6] = -1;
57+
#endif
58+
fields[7] = s->st_ino;
59+
fields[8] = s->st_size;
60+
#if defined(__POSIX__)
61+
fields[9] = s->st_blocks;
62+
#else
63+
fields[9] = -1;
64+
#endif
65+
// Dates.
66+
// NO-LINT because the fields are 'long' and we just want to cast to `unsigned`
67+
#define X(idx, name) \
68+
/* NOLINTNEXTLINE(runtime/int) */ \
69+
fields[idx] = ((unsigned long)(s->st_##name.tv_sec) * 1e3) + \
70+
/* NOLINTNEXTLINE(runtime/int) */ \
71+
((unsigned long)(s->st_##name.tv_nsec) / 1e6); \
72+
73+
X(10, atim)
74+
X(11, mtim)
75+
X(12, ctim)
76+
X(13, birthtim)
77+
#undef X
78+
}
79+
80+
namespace fs {
4581

4682
using v8::Array;
4783
using v8::ArrayBuffer;
@@ -67,60 +103,6 @@ using v8::Value;
67103

68104
#define GET_OFFSET(a) ((a)->IsNumber() ? (a)->IntegerValue() : -1)
69105

70-
class FSReqWrap: public ReqWrap<uv_fs_t> {
71-
public:
72-
enum Ownership { COPY, MOVE };
73-
74-
inline static FSReqWrap* New(Environment* env,
75-
Local<Object> req,
76-
const char* syscall,
77-
const char* data = nullptr,
78-
enum encoding encoding = UTF8,
79-
Ownership ownership = COPY);
80-
81-
inline void Dispose();
82-
83-
void ReleaseEarly() {
84-
if (data_ != inline_data()) {
85-
delete[] data_;
86-
data_ = nullptr;
87-
}
88-
}
89-
90-
const char* syscall() const { return syscall_; }
91-
const char* data() const { return data_; }
92-
const enum encoding encoding_;
93-
94-
size_t self_size() const override { return sizeof(*this); }
95-
96-
private:
97-
FSReqWrap(Environment* env,
98-
Local<Object> req,
99-
const char* syscall,
100-
const char* data,
101-
enum encoding encoding)
102-
: ReqWrap(env, req, AsyncWrap::PROVIDER_FSREQWRAP),
103-
encoding_(encoding),
104-
syscall_(syscall),
105-
data_(data) {
106-
Wrap(object(), this);
107-
}
108-
109-
~FSReqWrap() {
110-
ReleaseEarly();
111-
ClearWrap(object());
112-
}
113-
114-
void* operator new(size_t size) = delete;
115-
void* operator new(size_t size, char* storage) { return storage; }
116-
char* inline_data() { return reinterpret_cast<char*>(this + 1); }
117-
118-
const char* syscall_;
119-
const char* data_;
120-
121-
DISALLOW_COPY_AND_ASSIGN(FSReqWrap);
122-
};
123-
124106
#define ASSERT_PATH(path) \
125107
if (*path == nullptr) \
126108
return TYPE_ERROR( #path " must be a string or Buffer");
@@ -148,6 +130,19 @@ void FSReqWrap::Dispose() {
148130
}
149131

150132

133+
void FSReqWrap::Reject(Local<Value> reject) {
134+
Local<Value> argv[1] { reject };
135+
MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
136+
}
137+
138+
void FSReqWrap::Resolve(Local<Value> value) {
139+
Local<Value> argv[2] {
140+
Null(env()->isolate()),
141+
value
142+
};
143+
MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
144+
}
145+
151146
void NewFSReqWrap(const FunctionCallbackInfo<Value>& args) {
152147
CHECK(args.IsConstructCall());
153148
ClearWrap(args.This());
@@ -163,29 +158,23 @@ void After(uv_fs_t *req) {
163158
HandleScope handle_scope(env->isolate());
164159
Context::Scope context_scope(env->context());
165160

166-
// there is always at least one argument. "error"
167-
int argc = 1;
168-
169161
// Allocate space for two args. We may only use one depending on the case.
170162
// (Feel free to increase this if you need more)
171-
Local<Value> argv[2];
172163
MaybeLocal<Value> link;
173164
Local<Value> error;
174165

175166
if (req->result < 0) {
176167
// An error happened.
177-
argv[0] = UVException(env->isolate(),
178-
req->result,
179-
req_wrap->syscall(),
180-
nullptr,
181-
req->path,
182-
req_wrap->data());
168+
req_wrap->Reject(UVException(env->isolate(),
169+
req->result,
170+
req_wrap->syscall(),
171+
nullptr,
172+
req->path,
173+
req_wrap->data()));
183174
} else {
184175
// error value is empty or null for non-error.
185-
argv[0] = Null(env->isolate());
186-
187-
// All have at least two args now.
188-
argc = 2;
176+
Local<Value> ret = Undefined(env->isolate());
177+
bool reject = false;
189178

190179
switch (req->fs_type) {
191180
// These all have no data to pass.
@@ -205,74 +194,54 @@ void After(uv_fs_t *req) {
205194
case UV_FS_CHOWN:
206195
case UV_FS_FCHOWN:
207196
case UV_FS_COPYFILE:
197+
case UV_FS_UTIME:
198+
case UV_FS_FUTIME:
208199
// These, however, don't.
209-
argc = 1;
210200
break;
211201

212202
case UV_FS_STAT:
213203
case UV_FS_LSTAT:
214204
case UV_FS_FSTAT:
215-
argc = 1;
216205
FillStatsArray(env->fs_stats_field_array(),
217206
static_cast<const uv_stat_t*>(req->ptr));
218207
break;
219208

220-
case UV_FS_UTIME:
221-
case UV_FS_FUTIME:
222-
argc = 0;
223-
break;
224-
225209
case UV_FS_OPEN:
226-
argv[1] = Integer::New(env->isolate(), req->result);
227-
break;
228-
229210
case UV_FS_WRITE:
230-
argv[1] = Integer::New(env->isolate(), req->result);
211+
case UV_FS_READ:
212+
ret = Integer::New(env->isolate(), req->result);
231213
break;
232214

215+
233216
case UV_FS_MKDTEMP:
234217
{
235218
link = StringBytes::Encode(env->isolate(),
236219
static_cast<const char*>(req->path),
237220
req_wrap->encoding_,
238221
&error);
239222
if (link.IsEmpty()) {
240-
argv[0] = error;
223+
reject = true;
224+
ret = error;
241225
} else {
242-
argv[1] = link.ToLocalChecked();
226+
ret = link.ToLocalChecked();
243227
}
244228
break;
245229
}
246230

247231
case UV_FS_READLINK:
248-
link = StringBytes::Encode(env->isolate(),
249-
static_cast<const char*>(req->ptr),
250-
req_wrap->encoding_,
251-
&error);
252-
if (link.IsEmpty()) {
253-
argv[0] = error;
254-
} else {
255-
argv[1] = link.ToLocalChecked();
256-
}
257-
break;
258-
259232
case UV_FS_REALPATH:
260233
link = StringBytes::Encode(env->isolate(),
261234
static_cast<const char*>(req->ptr),
262235
req_wrap->encoding_,
263236
&error);
264237
if (link.IsEmpty()) {
265-
argv[0] = error;
238+
reject = true;
239+
ret = error;
266240
} else {
267-
argv[1] = link.ToLocalChecked();
241+
ret = link.ToLocalChecked();
268242
}
269243
break;
270244

271-
case UV_FS_READ:
272-
// Buffer interface
273-
argv[1] = Integer::New(env->isolate(), req->result);
274-
break;
275-
276245
case UV_FS_SCANDIR:
277246
{
278247
int r;
@@ -288,10 +257,9 @@ void After(uv_fs_t *req) {
288257
if (r == UV_EOF)
289258
break;
290259
if (r != 0) {
291-
argv[0] = UVException(r,
292-
nullptr,
293-
req_wrap->syscall(),
294-
static_cast<const char*>(req->path));
260+
reject = true;
261+
ret = UVException(r, nullptr, req_wrap->syscall(),
262+
static_cast<const char*>(req->path));
295263
break;
296264
}
297265

@@ -301,7 +269,8 @@ void After(uv_fs_t *req) {
301269
req_wrap->encoding_,
302270
&error);
303271
if (filename.IsEmpty()) {
304-
argv[0] = error;
272+
reject = true;
273+
ret = error;
305274
break;
306275
}
307276
name_argv[name_idx++] = filename.ToLocalChecked();
@@ -318,17 +287,19 @@ void After(uv_fs_t *req) {
318287
.ToLocalChecked();
319288
}
320289

321-
argv[1] = names;
290+
ret = names;
322291
}
323292
break;
324293

325294
default:
326295
CHECK(0 && "Unhandled eio response");
327296
}
297+
if (!reject)
298+
req_wrap->Resolve(ret);
299+
else
300+
req_wrap->Reject(ret);
328301
}
329302

330-
req_wrap->MakeCallback(env->oncomplete_string(), argc, argv);
331-
332303
uv_fs_req_cleanup(req_wrap->req());
333304
req_wrap->Dispose();
334305
}
@@ -471,41 +442,6 @@ void Close(const FunctionCallbackInfo<Value>& args) {
471442
}
472443
}
473444

474-
} // anonymous namespace
475-
476-
void FillStatsArray(double* fields, const uv_stat_t* s) {
477-
fields[0] = s->st_dev;
478-
fields[1] = s->st_mode;
479-
fields[2] = s->st_nlink;
480-
fields[3] = s->st_uid;
481-
fields[4] = s->st_gid;
482-
fields[5] = s->st_rdev;
483-
#if defined(__POSIX__)
484-
fields[6] = s->st_blksize;
485-
#else
486-
fields[6] = -1;
487-
#endif
488-
fields[7] = s->st_ino;
489-
fields[8] = s->st_size;
490-
#if defined(__POSIX__)
491-
fields[9] = s->st_blocks;
492-
#else
493-
fields[9] = -1;
494-
#endif
495-
// Dates.
496-
// NO-LINT because the fields are 'long' and we just want to cast to `unsigned`
497-
#define X(idx, name) \
498-
/* NOLINTNEXTLINE(runtime/int) */ \
499-
fields[idx] = ((unsigned long)(s->st_##name.tv_sec) * 1e3) + \
500-
/* NOLINTNEXTLINE(runtime/int) */ \
501-
((unsigned long)(s->st_##name.tv_nsec) / 1e6); \
502-
503-
X(10, atim)
504-
X(11, mtim)
505-
X(12, ctim)
506-
X(13, birthtim)
507-
#undef X
508-
}
509445

510446
// Used to speed up module loading. Returns the contents of the file as
511447
// a string or undefined when the file cannot be opened. Returns an empty
@@ -1460,6 +1396,8 @@ void InitFs(Local<Object> target,
14601396
target->Set(wrapString, fst->GetFunction());
14611397
}
14621398

1399+
} // namespace fs
1400+
14631401
} // end namespace node
14641402

1465-
NODE_BUILTIN_MODULE_CONTEXT_AWARE(fs, node::InitFs)
1403+
NODE_BUILTIN_MODULE_CONTEXT_AWARE(fs, node::fs::InitFs)

0 commit comments

Comments
 (0)