diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2018-04-07 17:01:06 +0800 |
---|---|---|
committer | Joyee Cheung <joyeec9h3@gmail.com> | 2018-06-07 22:05:23 +0800 |
commit | 1e7645c39ae5213a44267cff3d599264c2211f1a (patch) | |
tree | a000944a7267c0ad8b0dfe325d93f34f564844ed /src | |
parent | af2a1045631028dfad0dd5d3eb4c4866fdf55730 (diff) | |
download | android-node-v8-1e7645c39ae5213a44267cff3d599264c2211f1a.tar.gz android-node-v8-1e7645c39ae5213a44267cff3d599264c2211f1a.tar.bz2 android-node-v8-1e7645c39ae5213a44267cff3d599264c2211f1a.zip |
fs: support BigInt in fs.*stat and fs.watchFile
Add the `bigint: true` option to all the `fs.*stat` methods and
`fs.watchFile`.
PR-URL: https://github.com/nodejs/node/pull/20220
Fixes: https://github.com/nodejs/node/issues/12115
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'src')
-rw-r--r-- | src/env-inl.h | 5 | ||||
-rw-r--r-- | src/env.cc | 1 | ||||
-rw-r--r-- | src/env.h | 3 | ||||
-rw-r--r-- | src/node_file.cc | 59 | ||||
-rw-r--r-- | src/node_file.h | 19 | ||||
-rw-r--r-- | src/node_internals.h | 12 | ||||
-rw-r--r-- | src/node_stat_watcher.cc | 13 | ||||
-rw-r--r-- | src/node_stat_watcher.h | 3 |
8 files changed, 75 insertions, 40 deletions
diff --git a/src/env-inl.h b/src/env-inl.h index 1652448955..c84fdf0bb8 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -546,6 +546,11 @@ Environment::fs_stats_field_array() { return &fs_stats_field_array_; } +inline AliasedBuffer<uint64_t, v8::BigUint64Array>* +Environment::fs_stats_field_bigint_array() { + return &fs_stats_field_bigint_array_; +} + inline std::vector<std::unique_ptr<fs::FileHandleReadWrap>>& Environment::file_handle_read_wrap_freelist() { return file_handle_read_wrap_freelist_; diff --git a/src/env.cc b/src/env.cc index 8df59d1546..6f6e9f3920 100644 --- a/src/env.cc +++ b/src/env.cc @@ -116,6 +116,7 @@ Environment::Environment(IsolateData* isolate_data, #endif http_parser_buffer_(nullptr), fs_stats_field_array_(isolate_, kFsStatsFieldsLength * 2), + fs_stats_field_bigint_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()); @@ -694,6 +694,8 @@ class Environment { void set_debug_categories(const std::string& cats, bool enabled); inline AliasedBuffer<double, v8::Float64Array>* fs_stats_field_array(); + inline AliasedBuffer<uint64_t, v8::BigUint64Array>* + fs_stats_field_bigint_array(); // stat fields contains twice the number of entries because `fs.StatWatcher` // needs room to store data for *two* `fs.Stats` instances. @@ -914,6 +916,7 @@ class Environment { bool debug_enabled_[static_cast<int>(DebugCategory::CATEGORY_COUNT)] = {0}; AliasedBuffer<double, v8::Float64Array> fs_stats_field_array_; + AliasedBuffer<uint64_t, v8::BigUint64Array> fs_stats_field_bigint_array_; std::vector<std::unique_ptr<fs::FileHandleReadWrap>> file_handle_read_wrap_freelist_; diff --git a/src/node_file.cc b/src/node_file.cc index d4f3cbfcfb..a63e90fafb 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -49,6 +49,7 @@ namespace node { namespace fs { using v8::Array; +using v8::BigUint64Array; using v8::Context; using v8::EscapableHandleScope; using v8::Float64Array; @@ -413,7 +414,7 @@ void FSReqWrap::Reject(Local<Value> reject) { } void FSReqWrap::ResolveStat(const uv_stat_t* stat) { - Resolve(node::FillGlobalStatsArray(env(), stat)); + Resolve(node::FillGlobalStatsArray(env(), stat, use_bigint())); } void FSReqWrap::Resolve(Local<Value> value) { @@ -433,7 +434,7 @@ void FSReqWrap::SetReturnValue(const FunctionCallbackInfo<Value>& args) { void NewFSReqWrap(const FunctionCallbackInfo<Value>& args) { CHECK(args.IsConstructCall()); Environment* env = Environment::GetCurrent(args.GetIsolate()); - new FSReqWrap(env, args.This()); + new FSReqWrap(env, args.This(), args[0]->IsTrue()); } FSReqAfterScope::FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req) @@ -670,11 +671,16 @@ inline int SyncCall(Environment* env, Local<Value> ctx, FSReqWrapSync* req_wrap, return err; } -inline FSReqBase* GetReqWrap(Environment* env, Local<Value> value) { +inline FSReqBase* GetReqWrap(Environment* env, Local<Value> value, + bool use_bigint = false) { if (value->IsObject()) { return Unwrap<FSReqBase>(value.As<Object>()); } else if (value->StrictEquals(env->fs_use_promises_symbol())) { - return new FSReqPromise<double, Float64Array>(env); + if (use_bigint) { + return new FSReqPromise<uint64_t, BigUint64Array>(env, use_bigint); + } else { + return new FSReqPromise<double, Float64Array>(env, use_bigint); + } } return nullptr; } @@ -825,22 +831,23 @@ static void Stat(const FunctionCallbackInfo<Value>& args) { BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); - FSReqBase* req_wrap_async = GetReqWrap(env, args[1]); - if (req_wrap_async != nullptr) { // stat(path, req) + bool use_bigint = args[1]->IsTrue(); + FSReqBase* req_wrap_async = GetReqWrap(env, args[2], use_bigint); + if (req_wrap_async != nullptr) { // stat(path, use_bigint, req) AsyncCall(env, req_wrap_async, args, "stat", UTF8, AfterStat, uv_fs_stat, *path); - } else { // stat(path, undefined, ctx) - CHECK_EQ(argc, 3); + } else { // stat(path, use_bigint, undefined, ctx) + CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; FS_SYNC_TRACE_BEGIN(stat); - int err = SyncCall(env, args[2], &req_wrap_sync, "stat", uv_fs_stat, *path); + int err = SyncCall(env, args[3], &req_wrap_sync, "stat", uv_fs_stat, *path); FS_SYNC_TRACE_END(stat); if (err != 0) { return; // error info is in ctx } Local<Value> arr = node::FillGlobalStatsArray(env, - static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr)); + static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr), use_bigint); args.GetReturnValue().Set(arr); } } @@ -849,20 +856,21 @@ static void LStat(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); const int argc = args.Length(); - CHECK_GE(argc, 2); + CHECK_GE(argc, 3); BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); - FSReqBase* req_wrap_async = GetReqWrap(env, args[1]); - if (req_wrap_async != nullptr) { // lstat(path, req) + bool use_bigint = args[1]->IsTrue(); + FSReqBase* req_wrap_async = GetReqWrap(env, args[2], use_bigint); + if (req_wrap_async != nullptr) { // lstat(path, use_bigint, req) AsyncCall(env, req_wrap_async, args, "lstat", UTF8, AfterStat, uv_fs_lstat, *path); - } else { // lstat(path, undefined, ctx) - CHECK_EQ(argc, 3); + } else { // lstat(path, use_bigint, undefined, ctx) + CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; FS_SYNC_TRACE_BEGIN(lstat); - int err = SyncCall(env, args[2], &req_wrap_sync, "lstat", uv_fs_lstat, + int err = SyncCall(env, args[3], &req_wrap_sync, "lstat", uv_fs_lstat, *path); FS_SYNC_TRACE_END(lstat); if (err != 0) { @@ -870,7 +878,7 @@ static void LStat(const FunctionCallbackInfo<Value>& args) { } Local<Value> arr = node::FillGlobalStatsArray(env, - static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr)); + static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr), use_bigint); args.GetReturnValue().Set(arr); } } @@ -884,22 +892,23 @@ static void FStat(const FunctionCallbackInfo<Value>& args) { CHECK(args[0]->IsInt32()); int fd = args[0].As<Int32>()->Value(); - FSReqBase* req_wrap_async = GetReqWrap(env, args[1]); - if (req_wrap_async != nullptr) { // fstat(fd, req) + bool use_bigint = args[1]->IsTrue(); + FSReqBase* req_wrap_async = GetReqWrap(env, args[2], use_bigint); + if (req_wrap_async != nullptr) { // fstat(fd, use_bigint, req) AsyncCall(env, req_wrap_async, args, "fstat", UTF8, AfterStat, uv_fs_fstat, fd); - } else { // fstat(fd, undefined, ctx) - CHECK_EQ(argc, 3); + } else { // fstat(fd, use_bigint, undefined, ctx) + CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; FS_SYNC_TRACE_BEGIN(fstat); - int err = SyncCall(env, args[2], &req_wrap_sync, "fstat", uv_fs_fstat, fd); + int err = SyncCall(env, args[3], &req_wrap_sync, "fstat", uv_fs_fstat, fd); FS_SYNC_TRACE_END(fstat); if (err != 0) { return; // error info is in ctx } Local<Value> arr = node::FillGlobalStatsArray(env, - static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr)); + static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr), use_bigint); args.GetReturnValue().Set(arr); } } @@ -1911,6 +1920,10 @@ void Initialize(Local<Object> target, FIXED_ONE_BYTE_STRING(env->isolate(), "statValues"), env->fs_stats_field_array()->GetJSArray()).FromJust(); + target->Set(context, + FIXED_ONE_BYTE_STRING(env->isolate(), "bigintStatValues"), + env->fs_stats_field_bigint_array()->GetJSArray()).FromJust(); + StatWatcher::Initialize(env, target); // Create FunctionTemplate for FSReqWrap diff --git a/src/node_file.h b/src/node_file.h index 03e41097d5..a14a1b0f85 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -26,8 +26,9 @@ class FSReqBase : public ReqWrap<uv_fs_t> { public: typedef MaybeStackBuffer<char, 64> FSReqBuffer; - FSReqBase(Environment* env, Local<Object> req, AsyncWrap::ProviderType type) - : ReqWrap(env, req, type) { + FSReqBase(Environment* env, Local<Object> req, AsyncWrap::ProviderType type, + bool use_bigint) + : ReqWrap(env, req, type), use_bigint_(use_bigint) { } void Init(const char* syscall, @@ -66,11 +67,13 @@ class FSReqBase : public ReqWrap<uv_fs_t> { enum encoding encoding() const { return encoding_; } size_t self_size() const override { return sizeof(*this); } + bool use_bigint() const { return use_bigint_; } private: enum encoding encoding_ = UTF8; bool has_data_ = false; const char* syscall_ = nullptr; + bool use_bigint_ = false; // Typically, the content of buffer_ is something like a file name, so // something around 64 bytes should be enough. @@ -81,8 +84,8 @@ class FSReqBase : public ReqWrap<uv_fs_t> { class FSReqWrap : public FSReqBase { public: - FSReqWrap(Environment* env, Local<Object> req) - : FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQWRAP) { } + FSReqWrap(Environment* env, Local<Object> req, bool use_bigint) + : FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQWRAP, use_bigint) { } void Reject(Local<Value> reject) override; void Resolve(Local<Value> value) override; @@ -96,11 +99,12 @@ class FSReqWrap : public FSReqBase { template <typename NativeT = double, typename V8T = v8::Float64Array> class FSReqPromise : public FSReqBase { public: - explicit FSReqPromise(Environment* env) + explicit FSReqPromise(Environment* env, bool use_bigint) : FSReqBase(env, env->fsreqpromise_constructor_template() ->NewInstance(env->context()).ToLocalChecked(), - AsyncWrap::PROVIDER_FSREQPROMISE), + AsyncWrap::PROVIDER_FSREQPROMISE, + use_bigint), stats_field_array_(env->isolate(), env->kFsStatsFieldsLength) { auto resolver = Promise::Resolver::New(env->context()).ToLocalChecked(); object()->Set(env->context(), env->promise_string(), @@ -135,8 +139,7 @@ class FSReqPromise : public FSReqBase { } void ResolveStat(const uv_stat_t* stat) override { - node::FillStatsArray(&stats_field_array_, stat); - Resolve(stats_field_array_.GetJSArray()); + Resolve(node::FillStatsArray(&stats_field_array_, stat)); } void SetReturnValue(const FunctionCallbackInfo<Value>& args) override { diff --git a/src/node_internals.h b/src/node_internals.h index f76aacd7e8..49f1d4f230 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -337,14 +337,14 @@ v8::Local<v8::Value> FillStatsArray(AliasedBuffer<NativeT, V8T>* fields_ptr, #if defined(__POSIX__) fields[offset + 6] = s->st_blksize; #else - fields[offset + 6] = -1; + fields[offset + 6] = 0; #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; + fields[offset + 9] = 0; #endif // Dates. // NO-LINT because the fields are 'long' and we just want to cast to `unsigned` @@ -365,8 +365,14 @@ v8::Local<v8::Value> FillStatsArray(AliasedBuffer<NativeT, V8T>* fields_ptr, inline v8::Local<v8::Value> FillGlobalStatsArray(Environment* env, const uv_stat_t* s, + bool use_bigint = false, int offset = 0) { - return node::FillStatsArray(env->fs_stats_field_array(), s, offset); + if (use_bigint) { + return node::FillStatsArray( + env->fs_stats_field_bigint_array(), s, offset); + } else { + return node::FillStatsArray(env->fs_stats_field_array(), s, offset); + } } void SetupBootstrapObject(Environment* env, diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 3749c2e21f..3f7da197b2 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -75,9 +75,10 @@ void StatWatcher::Initialize(Environment* env, Local<Object> target) { } -StatWatcher::StatWatcher(Environment* env, Local<Object> wrap) +StatWatcher::StatWatcher(Environment* env, Local<Object> wrap, bool use_bigint) : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_STATWATCHER), - watcher_(new uv_fs_poll_t) { + watcher_(new uv_fs_poll_t), + use_bigint_(use_bigint) { MakeWeak(); uv_fs_poll_init(env->event_loop(), watcher_); watcher_->data = static_cast<void*>(this); @@ -102,8 +103,10 @@ void StatWatcher::Callback(uv_fs_poll_t* handle, HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); - Local<Value> arr = node::FillGlobalStatsArray(env, curr); - node::FillGlobalStatsArray(env, prev, env->kFsStatsFieldsLength); + Local<Value> arr = node::FillGlobalStatsArray(env, curr, + wrap->use_bigint_); + node::FillGlobalStatsArray(env, prev, wrap->use_bigint_, + env->kFsStatsFieldsLength); Local<Value> argv[2] { Integer::New(env->isolate(), status), @@ -116,7 +119,7 @@ void StatWatcher::Callback(uv_fs_poll_t* handle, void StatWatcher::New(const FunctionCallbackInfo<Value>& args) { CHECK(args.IsConstructCall()); Environment* env = Environment::GetCurrent(args); - new StatWatcher(env, args.This()); + new StatWatcher(env, args.This(), args[0]->IsTrue()); } bool StatWatcher::IsActive() { diff --git a/src/node_stat_watcher.h b/src/node_stat_watcher.h index 587203ff1e..0d0d263d5c 100644 --- a/src/node_stat_watcher.h +++ b/src/node_stat_watcher.h @@ -39,7 +39,7 @@ class StatWatcher : public AsyncWrap { static void Initialize(Environment* env, v8::Local<v8::Object> target); protected: - StatWatcher(Environment* env, v8::Local<v8::Object> wrap); + StatWatcher(Environment* env, v8::Local<v8::Object> wrap, bool use_bigint); static void New(const v8::FunctionCallbackInfo<v8::Value>& args); static void Start(const v8::FunctionCallbackInfo<v8::Value>& args); @@ -57,6 +57,7 @@ class StatWatcher : public AsyncWrap { bool IsActive(); uv_fs_poll_t* watcher_; + const bool use_bigint_; }; } // namespace node |