summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2018-04-07 17:01:06 +0800
committerJoyee Cheung <joyeec9h3@gmail.com>2018-06-07 22:05:23 +0800
commit1e7645c39ae5213a44267cff3d599264c2211f1a (patch)
treea000944a7267c0ad8b0dfe325d93f34f564844ed /src
parentaf2a1045631028dfad0dd5d3eb4c4866fdf55730 (diff)
downloadandroid-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.h5
-rw-r--r--src/env.cc1
-rw-r--r--src/env.h3
-rw-r--r--src/node_file.cc59
-rw-r--r--src/node_file.h19
-rw-r--r--src/node_internals.h12
-rw-r--r--src/node_stat_watcher.cc13
-rw-r--r--src/node_stat_watcher.h3
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());
diff --git a/src/env.h b/src/env.h
index ee734fe920..9ad316c063 100644
--- a/src/env.h
+++ b/src/env.h
@@ -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