diff --git a/src/node_file.cc b/src/node_file.cc index 62a7f864cfb682..a42f12912a1285 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -149,161 +149,155 @@ void NewFSReqWrap(const FunctionCallbackInfo& args) { } -void After(uv_fs_t *req) { +FSReqAfterScope::FSReqAfterScope(FSReqWrap* wrap, uv_fs_t* req) + : wrap_(wrap), + req_(req), + handle_scope_(wrap->env()->isolate()), + context_scope_(wrap->env()->context()) { + CHECK_EQ(wrap_->req(), req); + wrap_->ReleaseEarly(); // Free memory that's no longer used now. +} + +FSReqAfterScope::~FSReqAfterScope() { + uv_fs_req_cleanup(wrap_->req()); + wrap_->Dispose(); +} + +void FSReqAfterScope::Reject(uv_fs_t* req) { + wrap_->Reject(UVException(wrap_->env()->isolate(), + req->result, + wrap_->syscall(), + nullptr, + req->path, + wrap_->data())); +} + +bool FSReqAfterScope::Proceed() { + if (req_->result < 0) { + Reject(req_); + return false; + } + return true; +} + +void AfterNoArgs(uv_fs_t* req) { FSReqWrap* req_wrap = static_cast(req->data); - CHECK_EQ(req_wrap->req(), req); - req_wrap->ReleaseEarly(); // Free memory that's no longer used now. + FSReqAfterScope after(req_wrap, req); + + if (after.Proceed()) + req_wrap->Resolve(Undefined(req_wrap->env()->isolate())); +} +void AfterStat(uv_fs_t* req) { + FSReqWrap* req_wrap = static_cast(req->data); + FSReqAfterScope after(req_wrap, req); Environment* env = req_wrap->env(); - HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); - // Allocate space for two args. We may only use one depending on the case. - // (Feel free to increase this if you need more) + if (after.Proceed()) { + FillStatsArray(env->fs_stats_field_array(), + static_cast(req->ptr)); + req_wrap->Resolve(Undefined(req_wrap->env()->isolate())); + } +} + +void AfterInteger(uv_fs_t* req) { + FSReqWrap* req_wrap = static_cast(req->data); + FSReqAfterScope after(req_wrap, req); + + if (after.Proceed()) + req_wrap->Resolve(Integer::New(req_wrap->env()->isolate(), req->result)); +} + +void AfterStringPath(uv_fs_t* req) { + FSReqWrap* req_wrap = static_cast(req->data); + FSReqAfterScope after(req_wrap, req); + MaybeLocal link; Local error; - if (req->result < 0) { - // An error happened. - req_wrap->Reject(UVException(env->isolate(), - req->result, - req_wrap->syscall(), - nullptr, - req->path, - req_wrap->data())); - } else { - // error value is empty or null for non-error. - Local ret = Undefined(env->isolate()); - bool reject = false; - - switch (req->fs_type) { - // These all have no data to pass. - case UV_FS_ACCESS: - case UV_FS_CLOSE: - case UV_FS_RENAME: - case UV_FS_UNLINK: - case UV_FS_RMDIR: - case UV_FS_MKDIR: - case UV_FS_FTRUNCATE: - case UV_FS_FSYNC: - case UV_FS_FDATASYNC: - case UV_FS_LINK: - case UV_FS_SYMLINK: - case UV_FS_CHMOD: - case UV_FS_FCHMOD: - case UV_FS_CHOWN: - case UV_FS_FCHOWN: - case UV_FS_COPYFILE: - case UV_FS_UTIME: - case UV_FS_FUTIME: - // These, however, don't. - break; + if (after.Proceed()) { + link = StringBytes::Encode(req_wrap->env()->isolate(), + static_cast(req->path), + req_wrap->encoding_, + &error); + if (link.IsEmpty()) + req_wrap->Reject(error); + else + req_wrap->Resolve(link.ToLocalChecked()); + } +} - case UV_FS_STAT: - case UV_FS_LSTAT: - case UV_FS_FSTAT: - FillStatsArray(env->fs_stats_field_array(), - static_cast(req->ptr)); - break; +void AfterStringPtr(uv_fs_t* req) { + FSReqWrap* req_wrap = static_cast(req->data); + FSReqAfterScope after(req_wrap, req); - case UV_FS_OPEN: - case UV_FS_WRITE: - case UV_FS_READ: - ret = Integer::New(env->isolate(), req->result); - break; + MaybeLocal link; + Local error; + + if (after.Proceed()) { + link = StringBytes::Encode(req_wrap->env()->isolate(), + static_cast(req->ptr), + req_wrap->encoding_, + &error); + if (link.IsEmpty()) + req_wrap->Reject(error); + else + req_wrap->Resolve(link.ToLocalChecked()); + } +} + +void AfterScanDir(uv_fs_t* req) { + FSReqWrap* req_wrap = static_cast(req->data); + FSReqAfterScope after(req_wrap, req); + if (after.Proceed()) { + Environment* env = req_wrap->env(); + Local error; + int r; + Local names = Array::New(env->isolate(), 0); + Local fn = env->push_values_to_array_function(); + Local name_argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; + size_t name_idx = 0; + + for (int i = 0; ; i++) { + uv_dirent_t ent; - case UV_FS_MKDTEMP: - { - link = StringBytes::Encode(env->isolate(), - static_cast(req->path), - req_wrap->encoding_, - &error); - if (link.IsEmpty()) { - reject = true; - ret = error; - } else { - ret = link.ToLocalChecked(); - } + r = uv_fs_scandir_next(req, &ent); + if (r == UV_EOF) break; + if (r != 0) { + return req_wrap->Reject( + UVException(r, nullptr, req_wrap->syscall(), + static_cast(req->path))); } - case UV_FS_READLINK: - case UV_FS_REALPATH: - link = StringBytes::Encode(env->isolate(), - static_cast(req->ptr), - req_wrap->encoding_, - &error); - if (link.IsEmpty()) { - reject = true; - ret = error; - } else { - ret = link.ToLocalChecked(); - } - break; + MaybeLocal filename = + StringBytes::Encode(env->isolate(), + ent.name, + req_wrap->encoding_, + &error); + if (filename.IsEmpty()) + return req_wrap->Reject(error); - case UV_FS_SCANDIR: - { - int r; - Local names = Array::New(env->isolate(), 0); - Local fn = env->push_values_to_array_function(); - Local name_argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; - size_t name_idx = 0; - - for (int i = 0; ; i++) { - uv_dirent_t ent; - - r = uv_fs_scandir_next(req, &ent); - if (r == UV_EOF) - break; - if (r != 0) { - reject = true; - ret = UVException(r, nullptr, req_wrap->syscall(), - static_cast(req->path)); - break; - } - - MaybeLocal filename = - StringBytes::Encode(env->isolate(), - ent.name, - req_wrap->encoding_, - &error); - if (filename.IsEmpty()) { - reject = true; - ret = error; - break; - } - name_argv[name_idx++] = filename.ToLocalChecked(); - - if (name_idx >= arraysize(name_argv)) { - fn->Call(env->context(), names, name_idx, name_argv) - .ToLocalChecked(); - name_idx = 0; - } - } - - if (name_idx > 0) { - fn->Call(env->context(), names, name_idx, name_argv) - .ToLocalChecked(); - } - - ret = names; - } - break; + name_argv[name_idx++] = filename.ToLocalChecked(); - default: - CHECK(0 && "Unhandled eio response"); + if (name_idx >= arraysize(name_argv)) { + fn->Call(env->context(), names, name_idx, name_argv) + .ToLocalChecked(); + name_idx = 0; + } } - if (!reject) - req_wrap->Resolve(ret); - else - req_wrap->Reject(ret); - } - uv_fs_req_cleanup(req_wrap->req()); - req_wrap->Dispose(); + if (name_idx > 0) { + fn->Call(env->context(), names, name_idx, name_argv) + .ToLocalChecked(); + } + + req_wrap->Resolve(names); + } } + // This struct is only used on sync fs calls. // For async calls FSReqWrap is used. class fs_req_wrap { @@ -320,15 +314,15 @@ class fs_req_wrap { template inline FSReqWrap* AsyncDestCall(Environment* env, Local req, const char* dest, enum encoding enc, const char* syscall, - Func fn, Args... args) { + uv_fs_cb after, Func fn, Args... args) { FSReqWrap* req_wrap = FSReqWrap::New(env, req, syscall, dest, enc); - int err = fn(env->event_loop(), req_wrap->req(), args..., After); + int err = fn(env->event_loop(), req_wrap->req(), args..., after); req_wrap->Dispatched(); if (err < 0) { uv_fs_t* uv_req = req_wrap->req(); uv_req->result = err; uv_req->path = nullptr; - After(uv_req); + after(uv_req); req_wrap = nullptr; } @@ -338,11 +332,12 @@ inline FSReqWrap* AsyncDestCall(Environment* env, Local req, // Template counterpart of ASYNC_CALL template inline FSReqWrap* AsyncCall(Environment* env, Local req, - enum encoding enc, const char* syscall, Func fn, Args... args) { - return AsyncDestCall(env, req, nullptr, enc, syscall, fn, args...); + enum encoding enc, const char* syscall, uv_fs_cb after, + Func fn, Args... args) { + return AsyncDestCall(env, req, nullptr, enc, syscall, after, fn, args...); } -#define ASYNC_DEST_CALL(func, request, dest, encoding, ...) \ +#define ASYNC_DEST_CALL(after, func, request, dest, encoding, ...) \ Environment* env = Environment::GetCurrent(args); \ CHECK(request->IsObject()); \ FSReqWrap* req_wrap = FSReqWrap::New(env, request.As(), \ @@ -350,20 +345,20 @@ inline FSReqWrap* AsyncCall(Environment* env, Local req, int err = uv_fs_ ## func(env->event_loop(), \ req_wrap->req(), \ __VA_ARGS__, \ - After); \ + after); \ req_wrap->Dispatched(); \ if (err < 0) { \ uv_fs_t* uv_req = req_wrap->req(); \ uv_req->result = err; \ uv_req->path = nullptr; \ - After(uv_req); \ + after(uv_req); \ req_wrap = nullptr; \ } else { \ args.GetReturnValue().Set(req_wrap->persistent()); \ } -#define ASYNC_CALL(func, req, encoding, ...) \ - ASYNC_DEST_CALL(func, req, nullptr, encoding, __VA_ARGS__) \ +#define ASYNC_CALL(after, func, req, encoding, ...) \ + ASYNC_DEST_CALL(after, func, req, nullptr, encoding, __VA_ARGS__) \ // Template counterpart of SYNC_DEST_CALL template @@ -418,7 +413,7 @@ void Access(const FunctionCallbackInfo& args) { if (args[2]->IsObject()) { Local req_obj = args[2]->ToObject(context).ToLocalChecked(); FSReqWrap* req_wrap = AsyncCall( - env, req_obj, UTF8, "access", uv_fs_access, *path, mode); + env, req_obj, UTF8, "access", AfterNoArgs, uv_fs_access, *path, mode); if (req_wrap != nullptr) { args.GetReturnValue().Set(req_wrap->persistent()); } @@ -436,7 +431,7 @@ void Close(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { - ASYNC_CALL(close, args[1], UTF8, fd) + ASYNC_CALL(AfterNoArgs, close, args[1], UTF8, fd) } else { SYNC_CALL(close, 0, fd) } @@ -537,7 +532,7 @@ static void Stat(const FunctionCallbackInfo& args) { ASSERT_PATH(path) if (args[1]->IsObject()) { - ASYNC_CALL(stat, args[1], UTF8, *path) + ASYNC_CALL(AfterStat, stat, args[1], UTF8, *path) } else { SYNC_CALL(stat, *path, *path) FillStatsArray(env->fs_stats_field_array(), @@ -555,7 +550,7 @@ static void LStat(const FunctionCallbackInfo& args) { ASSERT_PATH(path) if (args[1]->IsObject()) { - ASYNC_CALL(lstat, args[1], UTF8, *path) + ASYNC_CALL(AfterStat, lstat, args[1], UTF8, *path) } else { SYNC_CALL(lstat, *path, *path) FillStatsArray(env->fs_stats_field_array(), @@ -571,7 +566,7 @@ static void FStat(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { - ASYNC_CALL(fstat, args[1], UTF8, fd) + ASYNC_CALL(AfterStat, fstat, args[1], UTF8, fd) } else { SYNC_CALL(fstat, nullptr, fd) FillStatsArray(env->fs_stats_field_array(), @@ -607,7 +602,8 @@ static void Symlink(const FunctionCallbackInfo& args) { } if (args[3]->IsObject()) { - ASYNC_DEST_CALL(symlink, args[3], *path, UTF8, *target, *path, flags) + ASYNC_DEST_CALL(AfterNoArgs, symlink, args[3], *path, + UTF8, *target, *path, flags) } else { SYNC_DEST_CALL(symlink, *target, *path, *target, *path, flags) } @@ -629,7 +625,7 @@ static void Link(const FunctionCallbackInfo& args) { ASSERT_PATH(dest) if (args[2]->IsObject()) { - ASYNC_DEST_CALL(link, args[2], *dest, UTF8, *src, *dest) + ASYNC_DEST_CALL(AfterNoArgs, link, args[2], *dest, UTF8, *src, *dest) } else { SYNC_DEST_CALL(link, *src, *dest, *src, *dest) } @@ -653,7 +649,7 @@ static void ReadLink(const FunctionCallbackInfo& args) { callback = args[2]; if (callback->IsObject()) { - ASYNC_CALL(readlink, callback, encoding, *path) + ASYNC_CALL(AfterStringPtr, readlink, callback, encoding, *path) } else { SYNC_CALL(readlink, *path, *path) const char* link_path = static_cast(SYNC_REQ.ptr); @@ -686,7 +682,8 @@ static void Rename(const FunctionCallbackInfo& args) { ASSERT_PATH(new_path) if (args[2]->IsObject()) { - ASYNC_DEST_CALL(rename, args[2], *new_path, UTF8, *old_path, *new_path) + ASYNC_DEST_CALL(AfterNoArgs, rename, args[2], *new_path, + UTF8, *old_path, *new_path) } else { SYNC_DEST_CALL(rename, *old_path, *new_path, *old_path, *new_path) } @@ -702,7 +699,7 @@ static void FTruncate(const FunctionCallbackInfo& args) { const int64_t len = args[1]->IntegerValue(); if (args[2]->IsObject()) { - ASYNC_CALL(ftruncate, args[2], UTF8, fd, len) + ASYNC_CALL(AfterNoArgs, ftruncate, args[2], UTF8, fd, len) } else { SYNC_CALL(ftruncate, 0, fd, len) } @@ -716,7 +713,7 @@ static void Fdatasync(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { - ASYNC_CALL(fdatasync, args[1], UTF8, fd) + ASYNC_CALL(AfterNoArgs, fdatasync, args[1], UTF8, fd) } else { SYNC_CALL(fdatasync, 0, fd) } @@ -730,7 +727,7 @@ static void Fsync(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsObject()) { - ASYNC_CALL(fsync, args[1], UTF8, fd) + ASYNC_CALL(AfterNoArgs, fsync, args[1], UTF8, fd) } else { SYNC_CALL(fsync, 0, fd) } @@ -746,7 +743,7 @@ static void Unlink(const FunctionCallbackInfo& args) { ASSERT_PATH(path) if (args[1]->IsObject()) { - ASYNC_CALL(unlink, args[1], UTF8, *path) + ASYNC_CALL(AfterNoArgs, unlink, args[1], UTF8, *path) } else { SYNC_CALL(unlink, *path, *path) } @@ -762,7 +759,7 @@ static void RMDir(const FunctionCallbackInfo& args) { ASSERT_PATH(path) if (args[1]->IsObject()) { - ASYNC_CALL(rmdir, args[1], UTF8, *path) + ASYNC_CALL(AfterNoArgs, rmdir, args[1], UTF8, *path) } else { SYNC_CALL(rmdir, *path, *path) } @@ -782,7 +779,7 @@ static void MKDir(const FunctionCallbackInfo& args) { int mode = static_cast(args[1]->Int32Value()); if (args[2]->IsObject()) { - ASYNC_CALL(mkdir, args[2], UTF8, *path, mode) + ASYNC_CALL(AfterNoArgs, mkdir, args[2], UTF8, *path, mode) } else { SYNC_CALL(mkdir, *path, *path, mode) } @@ -797,7 +794,7 @@ static void RealPath(const FunctionCallbackInfo& args) { const enum encoding encoding = ParseEncoding(env->isolate(), args[1], UTF8); if (args[2]->IsObject()) { - ASYNC_CALL(realpath, args[2], encoding, *path); + ASYNC_CALL(AfterStringPtr, realpath, args[2], encoding, *path); } else { SYNC_CALL(realpath, *path, *path); const char* link_path = static_cast(SYNC_REQ.ptr); @@ -833,7 +830,7 @@ static void ReadDir(const FunctionCallbackInfo& args) { callback = args[2]; if (callback->IsObject()) { - ASYNC_CALL(scandir, callback, encoding, *path, 0 /*flags*/) + ASYNC_CALL(AfterScanDir, scandir, callback, encoding, *path, 0 /*flags*/) } else { SYNC_CALL(scandir, *path, *path, 0 /*flags*/) @@ -902,7 +899,7 @@ static void Open(const FunctionCallbackInfo& args) { int mode = static_cast(args[2]->Int32Value()); if (args[3]->IsObject()) { - ASYNC_CALL(open, args[3], UTF8, *path, flags, mode) + ASYNC_CALL(AfterInteger, open, args[3], UTF8, *path, flags, mode) } else { SYNC_CALL(open, *path, *path, flags, mode) args.GetReturnValue().Set(SYNC_RESULT); @@ -927,7 +924,8 @@ static void CopyFile(const FunctionCallbackInfo& args) { int flags = args[2]->Int32Value(); if (args[3]->IsObject()) { - ASYNC_DEST_CALL(copyfile, args[3], *dest, UTF8, *src, *dest, flags) + ASYNC_DEST_CALL(AfterNoArgs, copyfile, args[3], *dest, + UTF8, *src, *dest, flags) } else { SYNC_DEST_CALL(copyfile, *src, *dest, *src, *dest, flags) } @@ -974,7 +972,7 @@ static void WriteBuffer(const FunctionCallbackInfo& args) { uv_buf_t uvbuf = uv_buf_init(const_cast(buf), len); if (req->IsObject()) { - ASYNC_CALL(write, req, UTF8, fd, &uvbuf, 1, pos) + ASYNC_CALL(AfterInteger, write, req, UTF8, fd, &uvbuf, 1, pos) return; } @@ -1013,7 +1011,7 @@ static void WriteBuffers(const FunctionCallbackInfo& args) { } if (req->IsObject()) { - ASYNC_CALL(write, req, UTF8, fd, *iovs, iovs.length(), pos) + ASYNC_CALL(AfterInteger, write, req, UTF8, fd, *iovs, iovs.length(), pos) return; } @@ -1081,13 +1079,13 @@ static void WriteString(const FunctionCallbackInfo& args) { &uvbuf, 1, pos, - After); + AfterInteger); req_wrap->Dispatched(); if (err < 0) { uv_fs_t* uv_req = req_wrap->req(); uv_req->result = err; uv_req->path = nullptr; - After(uv_req); + AfterInteger(uv_req); return; } @@ -1141,7 +1139,7 @@ static void Read(const FunctionCallbackInfo& args) { req = args[5]; if (req->IsObject()) { - ASYNC_CALL(read, req, UTF8, fd, &uvbuf, 1, pos); + ASYNC_CALL(AfterInteger, read, req, UTF8, fd, &uvbuf, 1, pos); } else { SYNC_CALL(read, 0, fd, &uvbuf, 1, pos) args.GetReturnValue().Set(SYNC_RESULT); @@ -1166,7 +1164,7 @@ static void Chmod(const FunctionCallbackInfo& args) { int mode = static_cast(args[1]->Int32Value()); if (args[2]->IsObject()) { - ASYNC_CALL(chmod, args[2], UTF8, *path, mode); + ASYNC_CALL(AfterNoArgs, chmod, args[2], UTF8, *path, mode); } else { SYNC_CALL(chmod, *path, *path, mode); } @@ -1186,7 +1184,7 @@ static void FChmod(const FunctionCallbackInfo& args) { int mode = static_cast(args[1]->Int32Value()); if (args[2]->IsObject()) { - ASYNC_CALL(fchmod, args[2], UTF8, fd, mode); + ASYNC_CALL(AfterNoArgs, fchmod, args[2], UTF8, fd, mode); } else { SYNC_CALL(fchmod, 0, fd, mode); } @@ -1218,7 +1216,7 @@ static void Chown(const FunctionCallbackInfo& args) { uv_gid_t gid = static_cast(args[2]->Uint32Value()); if (args[3]->IsObject()) { - ASYNC_CALL(chown, args[3], UTF8, *path, uid, gid); + ASYNC_CALL(AfterNoArgs, chown, args[3], UTF8, *path, uid, gid); } else { SYNC_CALL(chown, *path, *path, uid, gid); } @@ -1240,7 +1238,7 @@ static void FChown(const FunctionCallbackInfo& args) { uv_gid_t gid = static_cast(args[2]->Uint32Value()); if (args[3]->IsObject()) { - ASYNC_CALL(fchown, args[3], UTF8, fd, uid, gid); + ASYNC_CALL(AfterNoArgs, fchown, args[3], UTF8, fd, uid, gid); } else { SYNC_CALL(fchown, 0, fd, uid, gid); } @@ -1269,7 +1267,7 @@ static void UTimes(const FunctionCallbackInfo& args) { const double mtime = static_cast(args[2]->NumberValue()); if (args[3]->IsObject()) { - ASYNC_CALL(utime, args[3], UTF8, *path, atime, mtime); + ASYNC_CALL(AfterNoArgs, utime, args[3], UTF8, *path, atime, mtime); } else { SYNC_CALL(utime, *path, *path, atime, mtime); } @@ -1287,7 +1285,7 @@ static void FUTimes(const FunctionCallbackInfo& args) { const double mtime = static_cast(args[2]->NumberValue()); if (args[3]->IsObject()) { - ASYNC_CALL(futime, args[3], UTF8, fd, atime, mtime); + ASYNC_CALL(AfterNoArgs, futime, args[3], UTF8, fd, atime, mtime); } else { SYNC_CALL(futime, 0, fd, atime, mtime); } @@ -1304,7 +1302,7 @@ static void Mkdtemp(const FunctionCallbackInfo& args) { const enum encoding encoding = ParseEncoding(env->isolate(), args[1], UTF8); if (args[2]->IsObject()) { - ASYNC_CALL(mkdtemp, args[2], encoding, *tmpl); + ASYNC_CALL(AfterStringPath, mkdtemp, args[2], encoding, *tmpl); } else { SYNC_CALL(mkdtemp, *tmpl, *tmpl); const char* path = static_cast(SYNC_REQ.path); diff --git a/src/node_file.h b/src/node_file.h index 53515ac7558228..db85451b67a9df 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -1,24 +1,3 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - #ifndef SRC_NODE_FILE_H_ #define SRC_NODE_FILE_H_ @@ -29,8 +8,11 @@ namespace node { +using v8::Context; +using v8::HandleScope; using v8::Local; using v8::Object; +using v8::Undefined; using v8::Value; namespace fs { @@ -93,6 +75,22 @@ class FSReqWrap: public ReqWrap { DISALLOW_COPY_AND_ASSIGN(FSReqWrap); }; +class FSReqAfterScope { + public: + FSReqAfterScope(FSReqWrap* wrap, uv_fs_t* req); + ~FSReqAfterScope(); + + bool Proceed(); + + void Reject(uv_fs_t* req); + + private: + FSReqWrap* wrap_ = nullptr; + uv_fs_t* req_ = nullptr; + HandleScope handle_scope_; + Context::Scope context_scope_; +}; + } // namespace fs } // namespace node