Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/node_file-inl.h
1 #ifndef SRC_NODE_FILE_INL_H_ 2 #define SRC_NODE_FILE_INL_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include "node_file.h" 7 #include "req_wrap-inl.h" 8 9 namespace node { 10 namespace fs { 11 12 FSContinuationData::FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb) 13 : done_cb_(done_cb), req_(req), mode_(mode) { 14 } 15 16 void FSContinuationData::PushPath(std::string&& path) { 17 paths_.emplace_back(std::move(path)); 18 } 19 20 void FSContinuationData::PushPath(const std::string& path) { 21 paths_.push_back(path); 22 } 23 24 void FSContinuationData::MaybeSetFirstPath(const std::string& path) { 25 if (first_path_.empty()) { 26 first_path_ = path; 27 } 28 } 29 30 std::string FSContinuationData::PopPath() { 31 CHECK(!paths_.empty()); 32 std::string path = std::move(paths_.back()); 33 paths_.pop_back(); 34 return path; 35 } 36 37 void FSContinuationData::Done(int result) { 38 req_->result = result; 39 done_cb_(req_); 40 } 41 42 FSReqBase::FSReqBase(BindingData* binding_data, 43 v8::Local<v8::Object> req, 44 AsyncWrap::ProviderType type, 45 bool use_bigint) 46 : ReqWrap(binding_data->env(), req, type), 47 use_bigint_(use_bigint), 48 binding_data_(binding_data) { 49 } 50 51 void FSReqBase::Init(const char* syscall, 52 const char* data, 53 size_t len, 54 enum encoding encoding) { 55 syscall_ = syscall; 56 encoding_ = encoding; 57 58 if (data != nullptr) { 59 CHECK(!has_data_); 60 buffer_.AllocateSufficientStorage(len + 1); 61 buffer_.SetLengthAndZeroTerminate(len); 62 memcpy(*buffer_, data, len); 63 has_data_ = true; 64 } 65 } 66 67 FSReqBase::FSReqBuffer& 68 FSReqBase::Init(const char* syscall, size_t len, enum encoding encoding) { 69 syscall_ = syscall; 70 encoding_ = encoding; 71 72 buffer_.AllocateSufficientStorage(len + 1); 73 has_data_ = false; // so that the data does not show up in error messages 74 return buffer_; 75 } 76 77 FSReqCallback::FSReqCallback(BindingData* binding_data, 78 v8::Local<v8::Object> req, 79 bool use_bigint) 80 : FSReqBase(binding_data, 81 req, 82 AsyncWrap::PROVIDER_FSREQCALLBACK, 83 use_bigint) {} 84 85 template <typename NativeT, typename V8T> 86 void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields, 87 const uv_stat_t* s, 88 const size_t offset) { 89 #define SET_FIELD_WITH_STAT(stat_offset, stat) \ 90 fields->SetValue(offset + static_cast<size_t>(FsStatsOffset::stat_offset), \ 91 static_cast<NativeT>(stat)) 92 93 // On win32, time is stored in uint64_t and starts from 1601-01-01. 94 // libuv calculates tv_sec and tv_nsec from it and converts to signed long, 95 // which causes Y2038 overflow. On the other platforms it is safe to treat 96 // negative values as pre-epoch time. 97 #ifdef _WIN32 98 #define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \ 99 /* NOLINTNEXTLINE(runtime/int) */ \ 100 SET_FIELD_WITH_STAT(stat_offset, static_cast<unsigned long>(stat)) 101 #else 102 #define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \ 103 SET_FIELD_WITH_STAT(stat_offset, static_cast<double>(stat)) 104 #endif // _WIN32 105 106 SET_FIELD_WITH_STAT(kDev, s->st_dev); 107 SET_FIELD_WITH_STAT(kMode, s->st_mode); 108 SET_FIELD_WITH_STAT(kNlink, s->st_nlink); 109 SET_FIELD_WITH_STAT(kUid, s->st_uid); 110 SET_FIELD_WITH_STAT(kGid, s->st_gid); 111 SET_FIELD_WITH_STAT(kRdev, s->st_rdev); 112 SET_FIELD_WITH_STAT(kBlkSize, s->st_blksize); 113 SET_FIELD_WITH_STAT(kIno, s->st_ino); 114 SET_FIELD_WITH_STAT(kSize, s->st_size); 115 SET_FIELD_WITH_STAT(kBlocks, s->st_blocks); 116 117 SET_FIELD_WITH_TIME_STAT(kATimeSec, s->st_atim.tv_sec); 118 SET_FIELD_WITH_TIME_STAT(kATimeNsec, s->st_atim.tv_nsec); 119 SET_FIELD_WITH_TIME_STAT(kMTimeSec, s->st_mtim.tv_sec); 120 SET_FIELD_WITH_TIME_STAT(kMTimeNsec, s->st_mtim.tv_nsec); 121 SET_FIELD_WITH_TIME_STAT(kCTimeSec, s->st_ctim.tv_sec); 122 SET_FIELD_WITH_TIME_STAT(kCTimeNsec, s->st_ctim.tv_nsec); 123 SET_FIELD_WITH_TIME_STAT(kBirthTimeSec, s->st_birthtim.tv_sec); 124 SET_FIELD_WITH_TIME_STAT(kBirthTimeNsec, s->st_birthtim.tv_nsec); 125 126 #undef SET_FIELD_WITH_TIME_STAT 127 #undef SET_FIELD_WITH_STAT 128 } 129 130 v8::Local<v8::Value> FillGlobalStatsArray(BindingData* binding_data, 131 const bool use_bigint, 132 const uv_stat_t* s, 133 const bool second) { 134 const ptrdiff_t offset = 135 second ? static_cast<ptrdiff_t>(FsStatsOffset::kFsStatsFieldsNumber) : 0; 136 if (use_bigint) { 137 auto* const arr = &binding_data->stats_field_bigint_array; 138 FillStatsArray(arr, s, offset); 139 return arr->GetJSArray(); 140 } else { 141 auto* const arr = &binding_data->stats_field_array; 142 FillStatsArray(arr, s, offset); 143 return arr->GetJSArray(); 144 } 145 } 146 147 template <typename NativeT, typename V8T> 148 void FillStatFsArray(AliasedBufferBase<NativeT, V8T>* fields, 149 const uv_statfs_t* s) { 150 #define SET_FIELD(field, stat) \ 151 fields->SetValue(static_cast<size_t>(FsStatFsOffset::field), \ 152 static_cast<NativeT>(stat)) 153 154 SET_FIELD(kType, s->f_type); 155 SET_FIELD(kBSize, s->f_bsize); 156 SET_FIELD(kBlocks, s->f_blocks); 157 SET_FIELD(kBFree, s->f_bfree); 158 SET_FIELD(kBAvail, s->f_bavail); 159 SET_FIELD(kFiles, s->f_files); 160 SET_FIELD(kFFree, s->f_ffree); 161 162 #undef SET_FIELD 163 } 164 165 v8::Local<v8::Value> FillGlobalStatFsArray(BindingData* binding_data, 166 const bool use_bigint, 167 const uv_statfs_t* s) { 168 if (use_bigint) { 169 auto* const arr = &binding_data->statfs_field_bigint_array; 170 FillStatFsArray(arr, s); 171 return arr->GetJSArray(); 172 } else { 173 auto* const arr = &binding_data->statfs_field_array; 174 FillStatFsArray(arr, s); 175 return arr->GetJSArray(); 176 } 177 } 178 179 template <typename AliasedBufferT> 180 FSReqPromise<AliasedBufferT>* 181 FSReqPromise<AliasedBufferT>::New(BindingData* binding_data, 182 bool use_bigint) { 183 Environment* env = binding_data->env(); 184 v8::Local<v8::Object> obj; 185 if (!env->fsreqpromise_constructor_template() 186 ->NewInstance(env->context()) 187 .ToLocal(&obj)) { 188 return nullptr; 189 } 190 v8::Local<v8::Promise::Resolver> resolver; 191 if (!v8::Promise::Resolver::New(env->context()).ToLocal(&resolver) || 192 obj->Set(env->context(), env->promise_string(), resolver).IsNothing()) { 193 return nullptr; 194 } 195 return new FSReqPromise(binding_data, obj, use_bigint); 196 } 197 198 template <typename AliasedBufferT> 199 FSReqPromise<AliasedBufferT>::~FSReqPromise() { 200 // Validate that the promise was explicitly resolved or rejected but only if 201 // the Isolate is not terminating because in this case the promise might have 202 // not finished. 203 CHECK_IMPLIES(!finished_, !env()->can_call_into_js()); 204 } 205 206 template <typename AliasedBufferT> 207 FSReqPromise<AliasedBufferT>::FSReqPromise(BindingData* binding_data, 208 v8::Local<v8::Object> obj, 209 bool use_bigint) 210 : FSReqBase( 211 binding_data, obj, AsyncWrap::PROVIDER_FSREQPROMISE, use_bigint), 212 stats_field_array_( 213 env()->isolate(), 214 static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber)), 215 statfs_field_array_( 216 env()->isolate(), 217 static_cast<size_t>(FsStatFsOffset::kFsStatFsFieldsNumber)) {} 218 219 template <typename AliasedBufferT> 220 void FSReqPromise<AliasedBufferT>::Reject(v8::Local<v8::Value> reject) { 221 finished_ = true; 222 v8::HandleScope scope(env()->isolate()); 223 InternalCallbackScope callback_scope(this); 224 v8::Local<v8::Value> value; 225 if (!object() 226 ->Get(env()->context(), env()->promise_string()) 227 .ToLocal(&value)) { 228 // If we hit this, getting the value from the object failed and 229 // an error was likely scheduled. We could try to reject the promise 230 // but let's just allow the error to propagate. 231 return; 232 } 233 v8::Local<v8::Promise::Resolver> resolver = value.As<v8::Promise::Resolver>(); 234 USE(resolver->Reject(env()->context(), reject).FromJust()); 235 } 236 237 template <typename AliasedBufferT> 238 void FSReqPromise<AliasedBufferT>::Resolve(v8::Local<v8::Value> value) { 239 finished_ = true; 240 v8::HandleScope scope(env()->isolate()); 241 InternalCallbackScope callback_scope(this); 242 v8::Local<v8::Value> val; 243 if (!object()->Get(env()->context(), env()->promise_string()).ToLocal(&val)) { 244 // If we hit this, getting the value from the object failed and 245 // an error was likely scheduled. We could try to reject the promise 246 // but let's just allow the error to propagate. 247 return; 248 } 249 v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>(); 250 USE(resolver->Resolve(env()->context(), value).FromJust()); 251 } 252 253 template <typename AliasedBufferT> 254 void FSReqPromise<AliasedBufferT>::ResolveStat(const uv_stat_t* stat) { 255 FillStatsArray(&stats_field_array_, stat); 256 Resolve(stats_field_array_.GetJSArray()); 257 } 258 259 template <typename AliasedBufferT> 260 void FSReqPromise<AliasedBufferT>::ResolveStatFs(const uv_statfs_t* stat) { 261 FillStatFsArray(&statfs_field_array_, stat); 262 Resolve(statfs_field_array_.GetJSArray()); 263 } 264 265 template <typename AliasedBufferT> 266 void FSReqPromise<AliasedBufferT>::SetReturnValue( 267 const v8::FunctionCallbackInfo<v8::Value>& args) { 268 v8::Local<v8::Value> val; 269 if (!object()->Get(env()->context(), env()->promise_string()).ToLocal(&val)) { 270 // If we hit this, getting the value from the object failed and 271 // an error was likely scheduled. We could try to reject the promise 272 // but let's just allow the error to propagate. 273 return; 274 } 275 v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>(); 276 args.GetReturnValue().Set(resolver->GetPromise()); 277 } 278 279 template <typename AliasedBufferT> 280 void FSReqPromise<AliasedBufferT>::MemoryInfo(MemoryTracker* tracker) const { 281 FSReqBase::MemoryInfo(tracker); 282 tracker->TrackField("stats_field_array", stats_field_array_); 283 tracker->TrackField("statfs_field_array", statfs_field_array_); 284 } 285 286 FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args, 287 int index, 288 bool use_bigint) { 289 v8::Local<v8::Value> value = args[index]; 290 FSReqBase* result = nullptr; 291 if (value->IsObject()) { 292 result = Unwrap<FSReqBase>(value.As<v8::Object>()); 293 } else { 294 Realm* realm = Realm::GetCurrent(args); 295 BindingData* binding_data = realm->GetBindingData<BindingData>(); 296 297 if (value->StrictEquals(realm->isolate_data()->fs_use_promises_symbol())) { 298 if (use_bigint) { 299 result = 300 FSReqPromise<AliasedBigInt64Array>::New(binding_data, use_bigint); 301 } else { 302 result = 303 FSReqPromise<AliasedFloat64Array>::New(binding_data, use_bigint); 304 } 305 } 306 } 307 if (result != nullptr) { 308 result->SetReturnValue(args); 309 } 310 return result; 311 } 312 313 // Returns nullptr if the operation fails from the start. 314 template <typename Func, typename... Args> 315 FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap, 316 const v8::FunctionCallbackInfo<v8::Value>& args, 317 const char* syscall, const char* dest, 318 size_t len, enum encoding enc, uv_fs_cb after, 319 Func fn, Args... fn_args) { 320 CHECK_NOT_NULL(req_wrap); 321 req_wrap->Init(syscall, dest, len, enc); 322 int err = req_wrap->Dispatch(fn, fn_args..., after); 323 if (err < 0) { 324 uv_fs_t* uv_req = req_wrap->req(); 325 uv_req->result = err; 326 uv_req->path = nullptr; 327 after(uv_req); // after may delete req_wrap if there is an error 328 req_wrap = nullptr; 329 } 330 return req_wrap; 331 } 332 333 // Returns nullptr if the operation fails from the start. 334 template <typename Func, typename... Args> 335 FSReqBase* AsyncCall(Environment* env, 336 FSReqBase* req_wrap, 337 const v8::FunctionCallbackInfo<v8::Value>& args, 338 const char* syscall, enum encoding enc, 339 uv_fs_cb after, Func fn, Args... fn_args) { 340 return AsyncDestCall(env, req_wrap, args, 341 syscall, nullptr, 0, enc, 342 after, fn, fn_args...); 343 } 344 345 // Template counterpart of SYNC_CALL, except that it only puts 346 // the error number and the syscall in the context instead of 347 // creating an error in the C++ land. 348 // ctx must be checked using value->IsObject() before being passed. 349 template <typename Func, typename... Args> 350 int SyncCall(Environment* env, v8::Local<v8::Value> ctx, 351 FSReqWrapSync* req_wrap, const char* syscall, 352 Func fn, Args... args) { 353 env->PrintSyncTrace(); 354 int err = fn(env->event_loop(), &(req_wrap->req), args..., nullptr); 355 if (err < 0) { 356 v8::Local<v8::Context> context = env->context(); 357 v8::Local<v8::Object> ctx_obj = ctx.As<v8::Object>(); 358 v8::Isolate* isolate = env->isolate(); 359 ctx_obj->Set(context, 360 env->errno_string(), 361 v8::Integer::New(isolate, err)).Check(); 362 ctx_obj->Set(context, 363 env->syscall_string(), 364 OneByteString(isolate, syscall)).Check(); 365 } 366 return err; 367 } 368 369 // Similar to SyncCall but throws immediately if there is an error. 370 template <typename Predicate, typename Func, typename... Args> 371 int SyncCallAndThrowIf(Predicate should_throw, 372 Environment* env, 373 FSReqWrapSync* req_wrap, 374 Func fn, 375 Args... args) { 376 env->PrintSyncTrace(); 377 int result = fn(nullptr, &(req_wrap->req), args..., nullptr); 378 if (should_throw(result)) { 379 env->ThrowUVException(result, 380 req_wrap->syscall_p, 381 nullptr, 382 req_wrap->path_p, 383 req_wrap->dest_p); 384 } 385 return result; 386 } 387 388 constexpr bool is_uv_error(int result) { 389 return result < 0; 390 } 391 392 // Similar to SyncCall but throws immediately if there is an error. 393 template <typename Func, typename... Args> 394 int SyncCallAndThrowOnError(Environment* env, 395 FSReqWrapSync* req_wrap, 396 Func fn, 397 Args... args) { 398 return SyncCallAndThrowIf(is_uv_error, env, req_wrap, fn, args...); 399 } 400 401 } // namespace fs 402 } // namespace node 403 404 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 405 406 #endif // SRC_NODE_FILE_INL_H_