summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/env.cc2
-rw-r--r--src/env.h7
-rw-r--r--src/node_file.cc126
-rw-r--r--src/node_file.h64
-rw-r--r--src/node_internals.h44
-rw-r--r--src/node_stat_watcher.cc12
6 files changed, 126 insertions, 129 deletions
diff --git a/src/env.cc b/src/env.cc
index 16a24260f6..4be70036e3 100644
--- a/src/env.cc
+++ b/src/env.cc
@@ -104,7 +104,7 @@ Environment::Environment(IsolateData* isolate_data,
#endif
handle_cleanup_waiting_(0),
http_parser_buffer_(nullptr),
- fs_stats_field_array_(isolate_, kFsStatsFieldsLength),
+ fs_stats_field_array_(isolate_, kFsStatsFieldsLength * 2),
context_(context->GetIsolate(), context) {
// We'll be creating new objects so make sure we've entered the context.
v8::HandleScope handle_scope(isolate());
diff --git a/src/env.h b/src/env.h
index e6a4e1dc05..23758c8d12 100644
--- a/src/env.h
+++ b/src/env.h
@@ -644,6 +644,10 @@ class Environment {
inline AliasedBuffer<double, v8::Float64Array>* fs_stats_field_array();
+ // stat fields contains twice the number of entries because `fs.StatWatcher`
+ // needs room to store data for *two* `fs.Stats` instances.
+ static const int kFsStatsFieldsLength = 14;
+
inline std::vector<std::unique_ptr<fs::FileHandleReadWrap>>&
file_handle_read_wrap_freelist();
@@ -822,9 +826,6 @@ class Environment {
bool http_parser_buffer_in_use_ = false;
std::unique_ptr<http2::http2_state> http2_state_;
- // stat fields contains twice the number of entries because `fs.StatWatcher`
- // needs room to store data for *two* `fs.Stats` instances.
- static const int kFsStatsFieldsLength = 2 * 14;
AliasedBuffer<double, v8::Float64Array> fs_stats_field_array_;
std::vector<std::unique_ptr<fs::FileHandleReadWrap>>
diff --git a/src/node_file.cc b/src/node_file.cc
index 5e88f76c40..14d908cd6f 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -45,42 +45,6 @@
namespace node {
-void FillStatsArray(AliasedBuffer<double, v8::Float64Array>* fields_ptr,
- const uv_stat_t* s, int offset) {
- AliasedBuffer<double, v8::Float64Array>& fields = *fields_ptr;
- fields[offset + 0] = s->st_dev;
- fields[offset + 1] = s->st_mode;
- fields[offset + 2] = s->st_nlink;
- fields[offset + 3] = s->st_uid;
- fields[offset + 4] = s->st_gid;
- fields[offset + 5] = s->st_rdev;
-#if defined(__POSIX__)
- fields[offset + 6] = s->st_blksize;
-#else
- fields[offset + 6] = -1;
-#endif
- fields[offset + 7] = s->st_ino;
- fields[offset + 8] = s->st_size;
-#if defined(__POSIX__)
- fields[offset + 9] = s->st_blocks;
-#else
- fields[offset + 9] = -1;
-#endif
-// Dates.
-// NO-LINT because the fields are 'long' and we just want to cast to `unsigned`
-#define X(idx, name) \
- /* NOLINTNEXTLINE(runtime/int) */ \
- fields[offset + idx] = ((unsigned long)(s->st_##name.tv_sec) * 1e3) + \
- /* NOLINTNEXTLINE(runtime/int) */ \
- ((unsigned long)(s->st_##name.tv_nsec) / 1e6); \
-
- X(10, atim)
- X(11, mtim)
- X(12, ctim)
- X(13, birthtim)
-#undef X
-}
-
namespace fs {
using v8::Array;
@@ -432,12 +396,9 @@ void FSReqWrap::Reject(Local<Value> reject) {
MakeCallback(env()->oncomplete_string(), 1, &reject);
}
-void FSReqWrap::FillStatsArray(const uv_stat_t* stat) {
- node::FillStatsArray(env()->fs_stats_field_array(), stat);
-}
-
-void FSReqWrap::ResolveStat() {
- Resolve(Undefined(env()->isolate()));
+void FSReqWrap::ResolveStat(const uv_stat_t* stat) {
+ node::FillGlobalStatsArray(env(), stat);
+ Resolve(env()->fs_stats_field_array()->GetJSArray());
}
void FSReqWrap::Resolve(Local<Value> value) {
@@ -452,65 +413,12 @@ void FSReqWrap::SetReturnValue(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().SetUndefined();
}
-void FSReqPromise::SetReturnValue(const FunctionCallbackInfo<Value>& args) {
- Local<Context> context = env()->context();
- args.GetReturnValue().Set(
- object()->Get(context, env()->promise_string()).ToLocalChecked()
- .As<Promise::Resolver>()->GetPromise());
-}
-
void NewFSReqWrap(const FunctionCallbackInfo<Value>& args) {
CHECK(args.IsConstructCall());
Environment* env = Environment::GetCurrent(args.GetIsolate());
new FSReqWrap(env, args.This());
}
-FSReqPromise::FSReqPromise(Environment* env)
- : FSReqBase(env,
- env->fsreqpromise_constructor_template()
- ->NewInstance(env->context()).ToLocalChecked(),
- AsyncWrap::PROVIDER_FSREQPROMISE),
- stats_field_array_(env->isolate(), 14) {
- auto resolver = Promise::Resolver::New(env->context()).ToLocalChecked();
- object()->Set(env->context(), env->promise_string(),
- resolver).FromJust();
-}
-
-FSReqPromise::~FSReqPromise() {
- // Validate that the promise was explicitly resolved or rejected.
- CHECK(finished_);
-}
-
-void FSReqPromise::Reject(Local<Value> reject) {
- finished_ = true;
- HandleScope scope(env()->isolate());
- InternalCallbackScope callback_scope(this);
- Local<Value> value =
- object()->Get(env()->context(),
- env()->promise_string()).ToLocalChecked();
- Local<Promise::Resolver> resolver = value.As<Promise::Resolver>();
- resolver->Reject(env()->context(), reject).FromJust();
-}
-
-void FSReqPromise::FillStatsArray(const uv_stat_t* stat) {
- node::FillStatsArray(&stats_field_array_, stat);
-}
-
-void FSReqPromise::ResolveStat() {
- Resolve(stats_field_array_.GetJSArray());
-}
-
-void FSReqPromise::Resolve(Local<Value> value) {
- finished_ = true;
- HandleScope scope(env()->isolate());
- InternalCallbackScope callback_scope(this);
- Local<Value> val =
- object()->Get(env()->context(),
- env()->promise_string()).ToLocalChecked();
- Local<Promise::Resolver> resolver = val.As<Promise::Resolver>();
- resolver->Resolve(env()->context(), value).FromJust();
-}
-
FSReqAfterScope::FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req)
: wrap_(wrap),
req_(req),
@@ -563,8 +471,7 @@ void AfterStat(uv_fs_t* req) {
FSReqAfterScope after(req_wrap, req);
if (after.Proceed()) {
- req_wrap->FillStatsArray(&req->statbuf);
- req_wrap->ResolveStat();
+ req_wrap->ResolveStat(&req->statbuf);
}
}
@@ -751,7 +658,7 @@ inline FSReqBase* GetReqWrap(Environment* env, Local<Value> value) {
if (value->IsObject()) {
return Unwrap<FSReqBase>(value.As<Object>());
} else if (value->StrictEquals(env->fs_use_promises_symbol())) {
- return new FSReqPromise(env);
+ return new FSReqPromise<double, v8::Float64Array>(env);
}
return nullptr;
}
@@ -893,7 +800,7 @@ static void Stat(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
const int argc = args.Length();
- CHECK_GE(argc, 1);
+ CHECK_GE(argc, 2);
BufferValue path(env->isolate(), args[0]);
CHECK_NE(*path, nullptr);
@@ -907,8 +814,8 @@ static void Stat(const FunctionCallbackInfo<Value>& args) {
FSReqWrapSync req_wrap_sync;
int err = SyncCall(env, args[2], &req_wrap_sync, "stat", uv_fs_stat, *path);
if (err == 0) {
- FillStatsArray(env->fs_stats_field_array(),
- static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
+ node::FillGlobalStatsArray(env,
+ static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
}
}
}
@@ -917,7 +824,7 @@ static void LStat(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
const int argc = args.Length();
- CHECK_GE(argc, 1);
+ CHECK_GE(argc, 2);
BufferValue path(env->isolate(), args[0]);
CHECK_NE(*path, nullptr);
@@ -932,8 +839,8 @@ static void LStat(const FunctionCallbackInfo<Value>& args) {
int err = SyncCall(env, args[2], &req_wrap_sync, "lstat", uv_fs_lstat,
*path);
if (err == 0) {
- FillStatsArray(env->fs_stats_field_array(),
- static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
+ node::FillGlobalStatsArray(env,
+ static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
}
}
}
@@ -942,7 +849,7 @@ static void FStat(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
const int argc = args.Length();
- CHECK_GE(argc, 1);
+ CHECK_GE(argc, 2);
CHECK(args[0]->IsInt32());
int fd = args[0].As<Int32>()->Value();
@@ -956,8 +863,8 @@ static void FStat(const FunctionCallbackInfo<Value>& args) {
FSReqWrapSync req_wrap_sync;
int err = SyncCall(env, args[2], &req_wrap_sync, "fstat", uv_fs_fstat, fd);
if (err == 0) {
- FillStatsArray(env->fs_stats_field_array(),
- static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
+ node::FillGlobalStatsArray(env,
+ static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
}
}
}
@@ -1908,6 +1815,11 @@ void Initialize(Local<Object> target,
env->SetMethod(target, "mkdtemp", Mkdtemp);
+ target->Set(env->context(),
+ FIXED_ONE_BYTE_STRING(env->isolate(), "kFsStatsFieldsLength"),
+ Integer::New(env->isolate(), env->kFsStatsFieldsLength))
+ .FromJust();
+
target->Set(context,
FIXED_ONE_BYTE_STRING(env->isolate(), "statValues"),
env->fs_stats_field_array()->GetJSArray()).FromJust();
diff --git a/src/node_file.h b/src/node_file.h
index 1925e400f2..d6c8aa443c 100644
--- a/src/node_file.h
+++ b/src/node_file.h
@@ -61,10 +61,9 @@ class FSReqBase : public ReqWrap<uv_fs_t> {
return buffer_;
}
- virtual void FillStatsArray(const uv_stat_t* stat) = 0;
virtual void Reject(Local<Value> reject) = 0;
virtual void Resolve(Local<Value> value) = 0;
- virtual void ResolveStat() = 0;
+ virtual void ResolveStat(const uv_stat_t* stat) = 0;
virtual void SetReturnValue(const FunctionCallbackInfo<Value>& args) = 0;
const char* syscall() const { return syscall_; }
@@ -90,31 +89,72 @@ class FSReqWrap : public FSReqBase {
FSReqWrap(Environment* env, Local<Object> req)
: FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQWRAP) { }
- void FillStatsArray(const uv_stat_t* stat) override;
void Reject(Local<Value> reject) override;
void Resolve(Local<Value> value) override;
- void ResolveStat() override;
+ void ResolveStat(const uv_stat_t* stat) override;
void SetReturnValue(const FunctionCallbackInfo<Value>& args) override;
private:
DISALLOW_COPY_AND_ASSIGN(FSReqWrap);
};
+template <typename NativeT = double, typename V8T = v8::Float64Array>
class FSReqPromise : public FSReqBase {
public:
- explicit FSReqPromise(Environment* env);
+ explicit FSReqPromise(Environment* env)
+ : FSReqBase(env,
+ env->fsreqpromise_constructor_template()
+ ->NewInstance(env->context()).ToLocalChecked(),
+ AsyncWrap::PROVIDER_FSREQPROMISE),
+ stats_field_array_(env->isolate(), env->kFsStatsFieldsLength) {
+ auto resolver = Promise::Resolver::New(env->context()).ToLocalChecked();
+ object()->Set(env->context(), env->promise_string(),
+ resolver).FromJust();
+ }
- ~FSReqPromise() override;
+ ~FSReqPromise() override {
+ // Validate that the promise was explicitly resolved or rejected.
+ CHECK(finished_);
+ }
- void FillStatsArray(const uv_stat_t* stat) override;
- void Reject(Local<Value> reject) override;
- void Resolve(Local<Value> value) override;
- void ResolveStat() override;
- void SetReturnValue(const FunctionCallbackInfo<Value>& args) override;
+ void Reject(Local<Value> reject) override {
+ finished_ = true;
+ HandleScope scope(env()->isolate());
+ InternalCallbackScope callback_scope(this);
+ Local<Value> value =
+ object()->Get(env()->context(),
+ env()->promise_string()).ToLocalChecked();
+ Local<Promise::Resolver> resolver = value.As<Promise::Resolver>();
+ resolver->Reject(env()->context(), reject).FromJust();
+ }
+
+ void Resolve(Local<Value> value) override {
+ finished_ = true;
+ HandleScope scope(env()->isolate());
+ InternalCallbackScope callback_scope(this);
+ Local<Value> val =
+ object()->Get(env()->context(),
+ env()->promise_string()).ToLocalChecked();
+ Local<Promise::Resolver> resolver = val.As<Promise::Resolver>();
+ resolver->Resolve(env()->context(), value).FromJust();
+ }
+
+ void ResolveStat(const uv_stat_t* stat) override {
+ node::FillStatsArray(&stats_field_array_, stat);
+ Resolve(stats_field_array_.GetJSArray());
+ }
+
+ void SetReturnValue(const FunctionCallbackInfo<Value>& args) override {
+ Local<Value> val =
+ object()->Get(env()->context(),
+ env()->promise_string()).ToLocalChecked();
+ Local<Promise::Resolver> resolver = val.As<Promise::Resolver>();
+ args.GetReturnValue().Set(resolver->GetPromise());
+ }
private:
bool finished_ = false;
- AliasedBuffer<double, v8::Float64Array> stats_field_array_;
+ AliasedBuffer<NativeT, V8T> stats_field_array_;
DISALLOW_COPY_AND_ASSIGN(FSReqPromise);
};
diff --git a/src/node_internals.h b/src/node_internals.h
index 6439ccc7a2..8cc1aa1a8f 100644
--- a/src/node_internals.h
+++ b/src/node_internals.h
@@ -307,8 +307,48 @@ v8::Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
const char* warning,
const char* deprecation_code);
-void FillStatsArray(AliasedBuffer<double, v8::Float64Array>* fields_ptr,
- const uv_stat_t* s, int offset = 0);
+template <typename NativeT, typename V8T>
+void FillStatsArray(AliasedBuffer<NativeT, V8T>* fields_ptr,
+ const uv_stat_t* s, int offset = 0) {
+ AliasedBuffer<NativeT, V8T>& fields = *fields_ptr;
+ fields[offset + 0] = s->st_dev;
+ fields[offset + 1] = s->st_mode;
+ fields[offset + 2] = s->st_nlink;
+ fields[offset + 3] = s->st_uid;
+ fields[offset + 4] = s->st_gid;
+ fields[offset + 5] = s->st_rdev;
+#if defined(__POSIX__)
+ fields[offset + 6] = s->st_blksize;
+#else
+ fields[offset + 6] = -1;
+#endif
+ fields[offset + 7] = s->st_ino;
+ fields[offset + 8] = s->st_size;
+#if defined(__POSIX__)
+ fields[offset + 9] = s->st_blocks;
+#else
+ fields[offset + 9] = -1;
+#endif
+// Dates.
+// NO-LINT because the fields are 'long' and we just want to cast to `unsigned`
+#define X(idx, name) \
+ /* NOLINTNEXTLINE(runtime/int) */ \
+ fields[offset + idx] = ((unsigned long)(s->st_##name.tv_sec) * 1e3) + \
+ /* NOLINTNEXTLINE(runtime/int) */ \
+ ((unsigned long)(s->st_##name.tv_nsec) / 1e6); \
+
+ X(10, atim)
+ X(11, mtim)
+ X(12, ctim)
+ X(13, birthtim)
+#undef X
+}
+
+inline void FillGlobalStatsArray(Environment* env,
+ const uv_stat_t* s,
+ int offset = 0) {
+ node::FillStatsArray(env->fs_stats_field_array(), s, offset);
+}
void SetupProcessObject(Environment* env,
int argc,
diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc
index 32b416c466..2ff3af633f 100644
--- a/src/node_stat_watcher.cc
+++ b/src/node_stat_watcher.cc
@@ -107,10 +107,14 @@ void StatWatcher::Callback(uv_fs_poll_t* handle,
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
- FillStatsArray(env->fs_stats_field_array(), curr);
- FillStatsArray(env->fs_stats_field_array(), prev, 14);
- Local<Value> arg = Integer::New(env->isolate(), status);
- wrap->MakeCallback(env->onchange_string(), 1, &arg);
+ node::FillGlobalStatsArray(env, curr);
+ node::FillGlobalStatsArray(env, prev, env->kFsStatsFieldsLength);
+
+ Local<Value> argv[2] {
+ Integer::New(env->isolate(), status),
+ env->fs_stats_field_array()->GetJSArray()
+ };
+ wrap->MakeCallback(env->onchange_string(), arraysize(argv), argv);
}