|
diff --git a/src/env.h b/src/env.h |
|
index 1010d649c6..d41b855547 100644 |
|
--- a/src/env.h |
|
+++ b/src/env.h |
|
@@ -259,6 +259,7 @@ namespace node { |
|
V(context, v8::Context) \ |
|
V(domain_array, v8::Array) \ |
|
V(domains_stack_array, v8::Array) \ |
|
+ V(fs_stats_template, v8::ObjectTemplate) \ |
|
V(generic_internal_field_template, v8::ObjectTemplate) \ |
|
V(jsstream_constructor_template, v8::FunctionTemplate) \ |
|
V(module_load_list_array, v8::Array) \ |
|
diff --git a/src/node_file.cc b/src/node_file.cc |
|
index 4a0b1527d6..b598c629ba 100644 |
|
--- a/src/node_file.cc |
|
+++ b/src/node_file.cc |
|
@@ -50,6 +50,7 @@ namespace { |
|
using v8::Array; |
|
using v8::ArrayBuffer; |
|
using v8::Context; |
|
+using v8::Date; |
|
using v8::Float64Array; |
|
using v8::Function; |
|
using v8::FunctionCallbackInfo; |
|
@@ -58,8 +59,11 @@ using v8::HandleScope; |
|
using v8::Integer; |
|
using v8::Local; |
|
using v8::MaybeLocal; |
|
+using v8::Name; |
|
using v8::Number; |
|
using v8::Object; |
|
+using v8::ObjectTemplate; |
|
+using v8::PropertyCallbackInfo; |
|
using v8::String; |
|
using v8::Value; |
|
|
|
@@ -373,6 +377,64 @@ class fs_req_wrap { |
|
}; |
|
|
|
|
|
+MaybeLocal<Object> CreateStatsObject(Environment* env, Local<ArrayBuffer> fields) { |
|
+ Local<ObjectTemplate> tmpl = env->fs_stats_template(); |
|
+ auto maybe_obj = tmpl->NewInstance(env->context()); |
|
+ if (maybe_obj.IsEmpty()) |
|
+ return maybe_obj; |
|
+ auto obj = maybe_obj.ToLocalChecked(); |
|
+ obj->SetInternalField(0, fields); |
|
+ // obj->SetPrototype(env->context(), proto); |
|
+ return MaybeLocal<Object>(obj); |
|
+} |
|
+ |
|
+#define STATS_PROPS_NUM(V) \ |
|
+ V(0, dev, Dev) \ |
|
+ V(1, mode, Mode) \ |
|
+ V(2, nlink, Nlink) \ |
|
+ V(3, uid, Uid) \ |
|
+ V(4, gid, Gid) \ |
|
+ V(5, rdev, Rdev) \ |
|
+ V(6, blksize, Blksize) \ |
|
+ V(7, ino, Ino) \ |
|
+ V(8, size, Size) \ |
|
+ V(9, blocks, Blocks) |
|
+ |
|
+#define STATS_PROPS_DATE(V) \ |
|
+ V(10, atime, Atime) \ |
|
+ V(11, mtime, Mtime) \ |
|
+ V(12, ctime, Ctime) \ |
|
+ V(13, birthtime, Birthtime) |
|
+ |
|
+#define STATS_PROPS(V) \ |
|
+ STATS_PROPS_NUM(V) \ |
|
+ STATS_PROPS_DATE(V) |
|
+ |
|
+#define STATS_GETTER(ToJS, idx, prop, func_name) \ |
|
+ static void StatsAccessorGetter ## func_name( \ |
|
+ Local<Name> property, const PropertyCallbackInfo<Value>& info) { \ |
|
+ const auto env = Environment::GetCurrent(info); \ |
|
+ auto obj = info.This(); \ |
|
+ CHECK(obj->InternalFieldCount() >= 1); \ |
|
+ auto fields_arrbuf = obj->GetInternalField(0); \ |
|
+ CHECK(fields_arrbuf->IsArrayBuffer()); \ |
|
+ const double* fields = static_cast<double*>( \ |
|
+ fields_arrbuf.As<ArrayBuffer>()->GetContents().Data()); \ |
|
+ info.GetReturnValue().Set(ToJS(env, fields[idx])); \ |
|
+ } |
|
+#define DBL_TO_NUM(env, num) Number::New(env->isolate(), num) |
|
+#define DBL_TO_DATE(env, num) Date::New(env->context(), num).ToLocalChecked() |
|
+#define V(idx, prop, func_name) STATS_GETTER(DBL_TO_NUM, idx, prop, func_name) |
|
+STATS_PROPS_NUM(V) |
|
+#undef V |
|
+#define V(idx, prop, func_name) STATS_GETTER(DBL_TO_DATE, idx, prop, func_name) |
|
+STATS_PROPS_DATE(V) |
|
+#undef V |
|
+#undef DBL_TO_NUM |
|
+#undef DBL_TO_DATE |
|
+#undef STATS_GETTER |
|
+ |
|
+ |
|
#define ASYNC_DEST_CALL(func, request, dest, encoding, ...) \ |
|
Environment* env = Environment::GetCurrent(args); \ |
|
CHECK(request->IsObject()); \ |
|
@@ -574,8 +636,13 @@ static void Stat(const FunctionCallbackInfo<Value>& args) { |
|
ASYNC_CALL(stat, args[1], UTF8, *path) |
|
} else { |
|
SYNC_CALL(stat, *path, *path) |
|
- FillStatsArray(env->fs_stats_field_array(), |
|
+ Local<ArrayBuffer> stats_buf = ArrayBuffer::New(env->isolate(), sizeof(double) * 14); |
|
+ FillStatsArray(static_cast<double*>(stats_buf->GetContents().Data()), |
|
static_cast<const uv_stat_t*>(SYNC_REQ.ptr)); |
|
+ auto stats_maybe = CreateStatsObject(env, stats_buf); |
|
+ if (stats_maybe.IsEmpty()) |
|
+ return; |
|
+ args.GetReturnValue().Set(stats_maybe.ToLocalChecked()); |
|
} |
|
} |
|
|
|
@@ -1477,6 +1544,20 @@ void InitFs(Local<Object> target, |
|
fst->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "FSReqWrap")); |
|
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "FSReqWrap"), |
|
fst->GetFunction()); |
|
+ |
|
+ // Create ObjectTemplate for Stats |
|
+ Local<ObjectTemplate> stats_tmpl = |
|
+ ObjectTemplate::New(env->isolate()); |
|
+ stats_tmpl->SetInternalFieldCount(1); |
|
+ |
|
+#define V(idx, name, func_name) \ |
|
+ stats_tmpl->SetLazyDataProperty( \ |
|
+ FIXED_ONE_BYTE_STRING(env->isolate(), #name), \ |
|
+ StatsAccessorGetter ## func_name); |
|
+ STATS_PROPS(V) |
|
+#undef V |
|
+ |
|
+ env->set_fs_stats_template(stats_tmpl); |
|
} |
|
|
|
} // end namespace node |
|
|