@@ -49,40 +49,72 @@ using v8::Value;
4949
5050class FSReqWrap: public ReqWrap<uv_fs_t> {
5151 public:
52- void * operator new (size_t size) { return new char [size]; }
53- void * operator new (size_t size, char * storage) { return storage; }
52+ enum Ownership { COPY, MOVE };
53+
54+ inline static FSReqWrap* New (Environment* env,
55+ Local<Object> req,
56+ const char * syscall,
57+ const char * data = nullptr ,
58+ Ownership ownership = COPY);
59+
60+ inline void Dispose ();
5461
62+ void ReleaseEarly () {
63+ if (data_ != inline_data ()) {
64+ delete[] data_;
65+ data_ = nullptr ;
66+ }
67+ }
68+
69+ const char * syscall () const { return syscall_; }
70+ const char * data () const { return data_; }
71+
72+ private:
5573 FSReqWrap (Environment* env,
5674 Local<Object> req,
5775 const char * syscall,
58- char * data = nullptr )
59- : ReqWrap (env, req, AsyncWrap::PROVIDER_FSREQWRAP),
60- syscall_ (syscall),
61- data_ (data),
62- dest_len_ (0 ) {
76+ const char * data)
77+ : ReqWrap (env, req, AsyncWrap::PROVIDER_FSREQWRAP),
78+ syscall_ (syscall),
79+ data_ (data) {
6380 Wrap (object (), this );
6481 }
6582
66- void ReleaseEarly () {
67- if (data_ == nullptr )
68- return ;
69- delete[] data_;
70- data_ = nullptr ;
71- }
83+ ~FSReqWrap () { ReleaseEarly (); }
7284
73- inline const char * syscall () const { return syscall_; }
74- inline const char * dest () const { return dest_; }
75- inline unsigned int dest_len () const { return dest_len_; }
76- inline void dest_len (unsigned int dest_len) { dest_len_ = dest_len; }
85+ void * operator new (size_t size) = delete ;
86+ void * operator new (size_t size, char * storage) { return storage; }
87+ char * inline_data () { return reinterpret_cast <char *>(this + 1 ); }
7788
78- private:
7989 const char * syscall_;
80- char * data_;
81- unsigned int dest_len_;
82- char dest_[ 1 ] ;
90+ const char * data_;
91+
92+ DISALLOW_COPY_AND_ASSIGN (FSReqWrap) ;
8393};
8494
8595
96+ FSReqWrap* FSReqWrap::New (Environment* env,
97+ Local<Object> req,
98+ const char * syscall,
99+ const char * data,
100+ Ownership ownership) {
101+ const bool copy = (data != nullptr && ownership == COPY);
102+ const size_t size = copy ? 1 + strlen (data) : 0 ;
103+ FSReqWrap* that;
104+ char * const storage = new char [sizeof (*that) + size];
105+ that = new (storage) FSReqWrap (env, req, syscall, data);
106+ if (copy)
107+ that->data_ = static_cast <char *>(memcpy (that->inline_data (), data, size));
108+ return that;
109+ }
110+
111+
112+ void FSReqWrap::Dispose () {
113+ this ->~FSReqWrap ();
114+ delete[] reinterpret_cast <char *>(this );
115+ }
116+
117+
86118static void NewFSReqWrap (const FunctionCallbackInfo<Value>& args) {
87119 CHECK (args.IsConstructCall ());
88120}
@@ -111,13 +143,12 @@ static void After(uv_fs_t *req) {
111143
112144 if (req->result < 0 ) {
113145 // An error happened.
114- const char * dest = req_wrap->dest_len () > 0 ? req_wrap->dest () : nullptr ;
115146 argv[0 ] = UVException (env->isolate (),
116147 req->result ,
117148 req_wrap->syscall (),
118149 nullptr ,
119150 req->path ,
120- dest );
151+ req_wrap-> data () );
121152 } else {
122153 // error value is empty or null for non-error.
123154 argv[0 ] = Null (env->isolate ());
@@ -212,7 +243,7 @@ static void After(uv_fs_t *req) {
212243 req_wrap->MakeCallback (env->oncomplete_string (), argc, argv);
213244
214245 uv_fs_req_cleanup (&req_wrap->req_ );
215- delete req_wrap;
246+ req_wrap-> Dispose () ;
216247}
217248
218249// This struct is only used on sync fs calls.
@@ -225,20 +256,10 @@ struct fs_req_wrap {
225256};
226257
227258
228- #define ASYNC_DEST_CALL (func, req, dest_path , ...) \
259+ #define ASYNC_DEST_CALL (func, req, dest , ...) \
229260 Environment* env = Environment::GetCurrent(args); \
230- FSReqWrap* req_wrap; \
231- char * dest_str = (dest_path); \
232- int dest_len = dest_str == nullptr ? 0 : strlen(dest_str); \
233- char * storage = new char [sizeof (*req_wrap) + dest_len]; \
234261 CHECK (req->IsObject ()); \
235- req_wrap = new (storage) FSReqWrap(env, req.As<Object>(), #func); \
236- req_wrap->dest_len (dest_len); \
237- if (dest_str != nullptr ) { \
238- memcpy (const_cast <char *>(req_wrap->dest ()), \
239- dest_str, \
240- dest_len + 1 ); \
241- } \
262+ FSReqWrap* req_wrap = FSReqWrap::New(env, req.As<Object>(), #func, dest); \
242263 int err = uv_fs_ ## func(env->event_loop (), \
243264 &req_wrap->req_, \
244265 __VA_ARGS__, \
@@ -811,7 +832,7 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
811832 char * buf = nullptr ;
812833 int64_t pos;
813834 size_t len;
814- bool must_free = false ;
835+ FSReqWrap::Ownership ownership = FSReqWrap::COPY ;
815836
816837 // will assign buf and len if string was external
817838 if (!StringBytes::GetExternalParts (env->isolate (),
@@ -824,7 +845,7 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
824845 // StorageSize may return too large a char, so correct the actual length
825846 // by the write size
826847 len = StringBytes::Write (env->isolate (), buf, len, args[1 ], enc);
827- must_free = true ;
848+ ownership = FSReqWrap::MOVE ;
828849 }
829850 pos = GET_OFFSET (args[2 ]);
830851 req = args[4 ];
@@ -833,13 +854,13 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
833854
834855 if (!req->IsObject ()) {
835856 SYNC_CALL (write, nullptr , fd, &uvbuf, 1 , pos)
836- if (must_free )
857+ if (ownership == FSReqWrap::MOVE )
837858 delete[] buf;
838859 return args.GetReturnValue ().Set (SYNC_RESULT);
839860 }
840861
841862 FSReqWrap* req_wrap =
842- new FSReqWrap (env, req.As <Object>(), " write" , must_free ? buf : nullptr );
863+ FSReqWrap::New (env, req.As <Object>(), " write" , buf, ownership );
843864 int err = uv_fs_write (env->event_loop (),
844865 &req_wrap->req_ ,
845866 fd,
0 commit comments