Skip to content

Commit b50dd44

Browse files
jasnellMayaLekova
authored andcommitted
fs: add FSReqPromise
PR-URL: nodejs#18297 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent fc62d34 commit b50dd44

File tree

4 files changed

+138
-37
lines changed

4 files changed

+138
-37
lines changed

src/async_wrap.h

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace node {
3838
V(DNSCHANNEL) \
3939
V(FSEVENTWRAP) \
4040
V(FSREQWRAP) \
41+
V(FSREQPROMISE) \
4142
V(GETADDRINFOREQWRAP) \
4243
V(GETNAMEINFOREQWRAP) \
4344
V(HTTP2SESSION) \

src/env.h

+2
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ class ModuleWrap;
220220
V(preference_string, "preference") \
221221
V(priority_string, "priority") \
222222
V(produce_cached_data_string, "produceCachedData") \
223+
V(promise_string, "promise") \
223224
V(raw_string, "raw") \
224225
V(read_host_object_string, "_readHostObject") \
225226
V(readable_string, "readable") \
@@ -241,6 +242,7 @@ class ModuleWrap;
241242
V(sni_context_string, "sni_context") \
242243
V(stack_string, "stack") \
243244
V(status_string, "status") \
245+
V(statfields_string, "statFields") \
244246
V(stdio_string, "stdio") \
245247
V(subject_string, "subject") \
246248
V(subjectaltname_string, "subjectaltname") \

src/node_file.cc

+82-26
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ using v8::Local;
9797
using v8::MaybeLocal;
9898
using v8::Number;
9999
using v8::Object;
100+
using v8::Promise;
100101
using v8::String;
101102
using v8::Undefined;
102103
using v8::Value;
@@ -127,30 +128,75 @@ void FSReqWrap::Resolve(Local<Value> value) {
127128
MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
128129
}
129130

130-
void FSReqWrap::Init(const char* syscall,
131-
const char* data,
132-
size_t len,
133-
enum encoding encoding) {
134-
syscall_ = syscall;
135-
encoding_ = encoding;
136-
137-
if (data != nullptr) {
138-
CHECK_EQ(data_, nullptr);
139-
buffer_.AllocateSufficientStorage(len + 1);
140-
buffer_.SetLengthAndZeroTerminate(len);
141-
memcpy(*buffer_, data, len);
142-
data_ = *buffer_;
143-
}
144-
}
145-
146131
void NewFSReqWrap(const FunctionCallbackInfo<Value>& args) {
147132
CHECK(args.IsConstructCall());
148133
Environment* env = Environment::GetCurrent(args.GetIsolate());
149134
new FSReqWrap(env, args.This());
150135
}
151136

137+
FSReqPromise::FSReqPromise(Environment* env, Local<Object> req)
138+
: FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQPROMISE) {
139+
auto resolver = Promise::Resolver::New(env->context()).ToLocalChecked();
140+
req->Set(env->context(), env->promise_string(),
141+
resolver.As<Promise>()).FromJust();
142+
143+
Local<ArrayBuffer> ab =
144+
ArrayBuffer::New(env->isolate(), statFields_,
145+
sizeof(double) * 14,
146+
v8::ArrayBufferCreationMode::kInternalized);
147+
object()->Set(env->context(),
148+
env->statfields_string(),
149+
Float64Array::New(ab, 0, 14)).FromJust();
150+
}
151+
152+
FSReqPromise::~FSReqPromise() {
153+
// Validate that the promise was explicitly resolved or rejected.
154+
CHECK(finished_);
155+
}
156+
157+
void FSReqPromise::Reject(Local<Value> reject) {
158+
finished_ = true;
159+
InternalCallbackScope callback_scope(this);
160+
HandleScope scope(env()->isolate());
161+
Local<Value> value =
162+
object()->Get(env()->context(),
163+
env()->promise_string()).ToLocalChecked();
164+
CHECK(value->IsPromise());
165+
Local<Promise> promise = value.As<Promise>();
166+
Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>();
167+
resolver->Reject(env()->context(), reject);
168+
}
169+
170+
void FSReqPromise::FillStatsArray(const uv_stat_t* stat) {
171+
node::FillStatsArray(statFields_, stat);
172+
}
152173

153-
FSReqAfterScope::FSReqAfterScope(FSReqWrap* wrap, uv_fs_t* req)
174+
void FSReqPromise::ResolveStat() {
175+
Resolve(
176+
object()->Get(env()->context(),
177+
env()->statfields_string()).ToLocalChecked());
178+
}
179+
180+
void FSReqPromise::Resolve(Local<Value> value) {
181+
finished_ = true;
182+
InternalCallbackScope callback_scope(this);
183+
HandleScope scope(env()->isolate());
184+
Local<Value> val =
185+
object()->Get(env()->context(),
186+
env()->promise_string()).ToLocalChecked();
187+
CHECK(val->IsPromise());
188+
Local<Promise> promise = val.As<Promise>();
189+
Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>();
190+
resolver->Resolve(env()->context(), value);
191+
}
192+
193+
void NewFSReqPromise(const FunctionCallbackInfo<Value>& args) {
194+
CHECK(args.IsConstructCall());
195+
Environment* env = Environment::GetCurrent(args.GetIsolate());
196+
new FSReqPromise(env, args.This());
197+
}
198+
199+
FSReqAfterScope::FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req)
154200
: wrap_(wrap),
155201
req_(req),
156202
handle_scope_(wrap->env()->isolate()),
@@ -190,15 +236,15 @@ bool FSReqAfterScope::Proceed() {
190236
}
191237

192238
void AfterNoArgs(uv_fs_t* req) {
193-
FSReqWrap* req_wrap = static_cast<FSReqWrap*>(req->data);
239+
FSReqBase* req_wrap = static_cast<FSReqBase*>(req->data);
194240
FSReqAfterScope after(req_wrap, req);
195241

196242
if (after.Proceed())
197243
req_wrap->Resolve(Undefined(req_wrap->env()->isolate()));
198244
}
199245

200246
void AfterStat(uv_fs_t* req) {
201-
FSReqWrap* req_wrap = static_cast<FSReqWrap*>(req->data);
247+
FSReqBase* req_wrap = static_cast<FSReqBase*>(req->data);
202248
FSReqAfterScope after(req_wrap, req);
203249

204250
if (after.Proceed()) {
@@ -208,15 +254,15 @@ void AfterStat(uv_fs_t* req) {
208254
}
209255

210256
void AfterInteger(uv_fs_t* req) {
211-
FSReqWrap* req_wrap = static_cast<FSReqWrap*>(req->data);
257+
FSReqBase* req_wrap = static_cast<FSReqBase*>(req->data);
212258
FSReqAfterScope after(req_wrap, req);
213259

214260
if (after.Proceed())
215261
req_wrap->Resolve(Integer::New(req_wrap->env()->isolate(), req->result));
216262
}
217263

218264
void AfterStringPath(uv_fs_t* req) {
219-
FSReqWrap* req_wrap = static_cast<FSReqWrap*>(req->data);
265+
FSReqBase* req_wrap = static_cast<FSReqBase*>(req->data);
220266
FSReqAfterScope after(req_wrap, req);
221267

222268
MaybeLocal<Value> link;
@@ -235,7 +281,7 @@ void AfterStringPath(uv_fs_t* req) {
235281
}
236282

237283
void AfterStringPtr(uv_fs_t* req) {
238-
FSReqWrap* req_wrap = static_cast<FSReqWrap*>(req->data);
284+
FSReqBase* req_wrap = static_cast<FSReqBase*>(req->data);
239285
FSReqAfterScope after(req_wrap, req);
240286

241287
MaybeLocal<Value> link;
@@ -254,7 +300,7 @@ void AfterStringPtr(uv_fs_t* req) {
254300
}
255301

256302
void AfterScanDir(uv_fs_t* req) {
257-
FSReqWrap* req_wrap = static_cast<FSReqWrap*>(req->data);
303+
FSReqBase* req_wrap = static_cast<FSReqBase*>(req->data);
258304
FSReqAfterScope after(req_wrap, req);
259305

260306
if (after.Proceed()) {
@@ -318,12 +364,12 @@ class fs_req_wrap {
318364
};
319365

320366
template <typename Func, typename... Args>
321-
inline FSReqWrap* AsyncDestCall(Environment* env,
367+
inline FSReqBase* AsyncDestCall(Environment* env,
322368
const FunctionCallbackInfo<Value>& args,
323369
const char* syscall, const char* dest, size_t len,
324370
enum encoding enc, uv_fs_cb after, Func fn, Args... fn_args) {
325371
Local<Object> req = args[args.Length() - 1].As<Object>();
326-
FSReqWrap* req_wrap = Unwrap<FSReqWrap>(req);
372+
FSReqBase* req_wrap = Unwrap<FSReqBase>(req);
327373
CHECK_NE(req_wrap, nullptr);
328374
req_wrap->Init(syscall, dest, len, enc);
329375
int err = fn(env->event_loop(), req_wrap->req(), fn_args..., after);
@@ -343,7 +389,7 @@ inline FSReqWrap* AsyncDestCall(Environment* env,
343389
}
344390

345391
template <typename Func, typename... Args>
346-
inline FSReqWrap* AsyncCall(Environment* env,
392+
inline FSReqBase* AsyncCall(Environment* env,
347393
const FunctionCallbackInfo<Value>& args,
348394
const char* syscall, enum encoding enc,
349395
uv_fs_cb after, Func fn, Args... fn_args) {
@@ -1396,6 +1442,16 @@ void InitFs(Local<Object> target,
13961442
FIXED_ONE_BYTE_STRING(env->isolate(), "FSReqWrap");
13971443
fst->SetClassName(wrapString);
13981444
target->Set(context, wrapString, fst->GetFunction()).FromJust();
1445+
1446+
// Create Function Template for FSReqPromise
1447+
Local<FunctionTemplate> fpt =
1448+
FunctionTemplate::New(env->isolate(), NewFSReqPromise);
1449+
fpt->InstanceTemplate()->SetInternalFieldCount(1);
1450+
AsyncWrap::AddWrapMethods(env, fpt);
1451+
Local<String> promiseString =
1452+
FIXED_ONE_BYTE_STRING(env->isolate(), "FSReqPromise");
1453+
fpt->SetClassName(promiseString);
1454+
target->Set(context, promiseString, fpt->GetFunction()).FromJust();
13991455
}
14001456

14011457
} // namespace fs

src/node_file.h

+53-11
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,37 @@ using v8::Value;
1717

1818
namespace fs {
1919

20-
class FSReqWrap : public ReqWrap<uv_fs_t> {
20+
class FSReqBase : public ReqWrap<uv_fs_t> {
2121
public:
22-
FSReqWrap(Environment* env, Local<Object> req)
23-
: ReqWrap(env, req, AsyncWrap::PROVIDER_FSREQWRAP) {
22+
FSReqBase(Environment* env, Local<Object> req, AsyncWrap::ProviderType type)
23+
: ReqWrap(env, req, type) {
2424
Wrap(object(), this);
2525
}
2626

27-
virtual ~FSReqWrap() {
27+
virtual ~FSReqBase() {
2828
ClearWrap(object());
2929
}
3030

3131
void Init(const char* syscall,
3232
const char* data = nullptr,
3333
size_t len = 0,
34-
enum encoding encoding = UTF8);
34+
enum encoding encoding = UTF8) {
35+
syscall_ = syscall;
36+
encoding_ = encoding;
37+
38+
if (data != nullptr) {
39+
CHECK_EQ(data_, nullptr);
40+
buffer_.AllocateSufficientStorage(len + 1);
41+
buffer_.SetLengthAndZeroTerminate(len);
42+
memcpy(*buffer_, data, len);
43+
data_ = *buffer_;
44+
}
45+
}
3546

36-
virtual void FillStatsArray(const uv_stat_t* stat);
37-
virtual void Reject(Local<Value> reject);
38-
virtual void Resolve(Local<Value> value);
39-
virtual void ResolveStat();
47+
virtual void FillStatsArray(const uv_stat_t* stat) = 0;
48+
virtual void Reject(Local<Value> reject) = 0;
49+
virtual void Resolve(Local<Value> value) = 0;
50+
virtual void ResolveStat() = 0;
4051

4152
const char* syscall() const { return syscall_; }
4253
const char* data() const { return data_; }
@@ -51,20 +62,51 @@ class FSReqWrap : public ReqWrap<uv_fs_t> {
5162
const char* data_ = nullptr;
5263
MaybeStackBuffer<char> buffer_;
5364

65+
DISALLOW_COPY_AND_ASSIGN(FSReqBase);
66+
};
67+
68+
class FSReqWrap : public FSReqBase {
69+
public:
70+
FSReqWrap(Environment* env, Local<Object> req)
71+
: FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQWRAP) { }
72+
73+
void FillStatsArray(const uv_stat_t* stat) override;
74+
void Reject(Local<Value> reject) override;
75+
void Resolve(Local<Value> value) override;
76+
void ResolveStat() override;
77+
78+
private:
5479
DISALLOW_COPY_AND_ASSIGN(FSReqWrap);
5580
};
5681

82+
class FSReqPromise : public FSReqBase {
83+
public:
84+
FSReqPromise(Environment* env, Local<Object> req);
85+
86+
~FSReqPromise() override;
87+
88+
void FillStatsArray(const uv_stat_t* stat) override;
89+
void Reject(Local<Value> reject) override;
90+
void Resolve(Local<Value> value) override;
91+
void ResolveStat() override;
92+
93+
private:
94+
bool finished_ = false;
95+
double statFields_[14] {};
96+
DISALLOW_COPY_AND_ASSIGN(FSReqPromise);
97+
};
98+
5799
class FSReqAfterScope {
58100
public:
59-
FSReqAfterScope(FSReqWrap* wrap, uv_fs_t* req);
101+
FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req);
60102
~FSReqAfterScope();
61103

62104
bool Proceed();
63105

64106
void Reject(uv_fs_t* req);
65107

66108
private:
67-
FSReqWrap* wrap_ = nullptr;
109+
FSReqBase* wrap_ = nullptr;
68110
uv_fs_t* req_ = nullptr;
69111
HandleScope handle_scope_;
70112
Context::Scope context_scope_;

0 commit comments

Comments
 (0)