@@ -148,6 +148,92 @@ class FSReqCallback : public FSReqBase {
148148 DISALLOW_COPY_AND_ASSIGN (FSReqCallback);
149149};
150150
151+ // Wordaround a GCC4.9 bug that C++14 N3652 was not implemented
152+ // Refs: https://www.gnu.org/software/gcc/projects/cxx-status.html#cxx14
153+ // Refs: https://isocpp.org/files/papers/N3652.html
154+ #if __cpp_constexpr < 201304
155+ # define constexpr inline
156+ #endif
157+
158+ template <typename NativeT,
159+ // SFINAE limit NativeT to arithmetic types
160+ typename = std::enable_if<std::is_arithmetic<NativeT>::value>>
161+ constexpr NativeT ToNative (uv_timespec_t ts) {
162+ // This template has exactly two specializations below.
163+ static_assert (std::is_arithmetic<NativeT>::value == false , " Not implemented" );
164+ UNREACHABLE ();
165+ }
166+
167+ template <>
168+ constexpr double ToNative (uv_timespec_t ts) {
169+ // We need to do a static_cast since the original FS values are ulong.
170+ /* NOLINTNEXTLINE(runtime/int) */
171+ const auto u_sec = static_cast <unsigned long >(ts.tv_sec );
172+ const double full_sec = u_sec * 1000.0 ;
173+ /* NOLINTNEXTLINE(runtime/int) */
174+ const auto u_nsec = static_cast <unsigned long >(ts.tv_nsec );
175+ const double full_nsec = u_nsec / 1000'000.0 ;
176+ return full_sec + full_nsec;
177+ }
178+
179+ template <>
180+ constexpr uint64_t ToNative (uv_timespec_t ts) {
181+ // We need to do a static_cast since the original FS values are ulong.
182+ /* NOLINTNEXTLINE(runtime/int) */
183+ const auto u_sec = static_cast <unsigned long >(ts.tv_sec );
184+ const auto full_sec = static_cast <uint64_t >(u_sec) * 1000UL ;
185+ /* NOLINTNEXTLINE(runtime/int) */
186+ const auto u_nsec = static_cast <unsigned long >(ts.tv_nsec );
187+ const auto full_nsec = static_cast <uint64_t >(u_nsec) / 1000'000UL ;
188+ return full_sec + full_nsec;
189+ }
190+
191+ #undef constexpr // end N3652 bug workaround
192+
193+ template <typename NativeT, typename V8T>
194+ constexpr void FillStatsArray (AliasedBuffer<NativeT, V8T>* fields,
195+ const uv_stat_t * s, const size_t offset = 0 ) {
196+ fields->SetValue (offset + 0 , s->st_dev );
197+ fields->SetValue (offset + 1 , s->st_mode );
198+ fields->SetValue (offset + 2 , s->st_nlink );
199+ fields->SetValue (offset + 3 , s->st_uid );
200+ fields->SetValue (offset + 4 , s->st_gid );
201+ fields->SetValue (offset + 5 , s->st_rdev );
202+ #if defined(__POSIX__)
203+ fields->SetValue (offset + 6 , s->st_blksize );
204+ #else
205+ fields->SetValue (offset + 6 , 0 );
206+ #endif
207+ fields->SetValue (offset + 7 , s->st_ino );
208+ fields->SetValue (offset + 8 , s->st_size );
209+ #if defined(__POSIX__)
210+ fields->SetValue (offset + 9 , s->st_blocks );
211+ #else
212+ fields->SetValue (offset + 9 , 0 );
213+ #endif
214+ // Dates.
215+ fields->SetValue (offset + 10 , ToNative<NativeT>(s->st_atim ));
216+ fields->SetValue (offset + 11 , ToNative<NativeT>(s->st_mtim ));
217+ fields->SetValue (offset + 12 , ToNative<NativeT>(s->st_ctim ));
218+ fields->SetValue (offset + 13 , ToNative<NativeT>(s->st_birthtim ));
219+ }
220+
221+ inline Local<Value> FillGlobalStatsArray (Environment* env,
222+ const bool use_bigint,
223+ const uv_stat_t * s,
224+ const bool second = false ) {
225+ const ptrdiff_t offset = second ? kFsStatsFieldsNumber : 0 ;
226+ if (use_bigint) {
227+ auto * const arr = env->fs_stats_field_bigint_array ();
228+ FillStatsArray (arr, s, offset);
229+ return arr->GetJSArray ();
230+ } else {
231+ auto * const arr = env->fs_stats_field_array ();
232+ FillStatsArray (arr, s, offset);
233+ return arr->GetJSArray ();
234+ }
235+ }
236+
151237template <typename NativeT = double , typename V8T = v8::Float64Array>
152238class FSReqPromise : public FSReqBase {
153239 public:
@@ -157,7 +243,7 @@ class FSReqPromise : public FSReqBase {
157243 ->NewInstance(env->context ()).ToLocalChecked(),
158244 AsyncWrap::PROVIDER_FSREQPROMISE,
159245 use_bigint),
160- stats_field_array_(env->isolate (), env->kFsStatsFieldsLength ) {
246+ stats_field_array_(env->isolate (), kFsStatsFieldsNumber ) {
161247 auto resolver = Promise::Resolver::New (env->context ()).ToLocalChecked ();
162248 object ()->Set (env->context (), env->promise_string (),
163249 resolver).FromJust ();
@@ -191,7 +277,8 @@ class FSReqPromise : public FSReqBase {
191277 }
192278
193279 void ResolveStat (const uv_stat_t * stat) override {
194- Resolve (node::FillStatsArray (&stats_field_array_, stat));
280+ FillStatsArray (&stats_field_array_, stat);
281+ Resolve (stats_field_array_.GetJSArray ());
195282 }
196283
197284 void SetReturnValue (const FunctionCallbackInfo<Value>& args) override {
0 commit comments