@@ -49,40 +49,72 @@ using v8::Value;
49
49
50
50
class FSReqWrap: public ReqWrap<uv_fs_t> {
51
51
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 ();
54
61
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:
55
73
FSReqWrap (Environment* env,
56
74
Local<Object> req,
57
75
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) {
63
80
Wrap (object (), this );
64
81
}
65
82
66
- void ReleaseEarly () {
67
- if (data_ == nullptr )
68
- return ;
69
- delete[] data_;
70
- data_ = nullptr ;
71
- }
83
+ ~FSReqWrap () { ReleaseEarly (); }
72
84
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 ); }
77
88
78
- private:
79
89
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) ;
83
93
};
84
94
85
95
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
+
86
118
static void NewFSReqWrap (const FunctionCallbackInfo<Value>& args) {
87
119
CHECK (args.IsConstructCall ());
88
120
}
@@ -111,13 +143,12 @@ static void After(uv_fs_t *req) {
111
143
112
144
if (req->result < 0 ) {
113
145
// An error happened.
114
- const char * dest = req_wrap->dest_len () > 0 ? req_wrap->dest () : nullptr ;
115
146
argv[0 ] = UVException (env->isolate (),
116
147
req->result ,
117
148
req_wrap->syscall (),
118
149
nullptr ,
119
150
req->path ,
120
- dest );
151
+ req_wrap-> data () );
121
152
} else {
122
153
// error value is empty or null for non-error.
123
154
argv[0 ] = Null (env->isolate ());
@@ -212,7 +243,7 @@ static void After(uv_fs_t *req) {
212
243
req_wrap->MakeCallback (env->oncomplete_string (), argc, argv);
213
244
214
245
uv_fs_req_cleanup (&req_wrap->req_ );
215
- delete req_wrap;
246
+ req_wrap-> Dispose () ;
216
247
}
217
248
218
249
// This struct is only used on sync fs calls.
@@ -225,20 +256,10 @@ struct fs_req_wrap {
225
256
};
226
257
227
258
228
- #define ASYNC_DEST_CALL (func, req, dest_path , ...) \
259
+ #define ASYNC_DEST_CALL (func, req, dest , ...) \
229
260
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]; \
234
261
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); \
242
263
int err = uv_fs_ ## func(env->event_loop (), \
243
264
&req_wrap->req_, \
244
265
__VA_ARGS__, \
@@ -811,7 +832,7 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
811
832
char * buf = nullptr ;
812
833
int64_t pos;
813
834
size_t len;
814
- bool must_free = false ;
835
+ FSReqWrap::Ownership ownership = FSReqWrap::COPY ;
815
836
816
837
// will assign buf and len if string was external
817
838
if (!StringBytes::GetExternalParts (env->isolate (),
@@ -824,7 +845,7 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
824
845
// StorageSize may return too large a char, so correct the actual length
825
846
// by the write size
826
847
len = StringBytes::Write (env->isolate (), buf, len, args[1 ], enc);
827
- must_free = true ;
848
+ ownership = FSReqWrap::MOVE ;
828
849
}
829
850
pos = GET_OFFSET (args[2 ]);
830
851
req = args[4 ];
@@ -833,13 +854,13 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
833
854
834
855
if (!req->IsObject ()) {
835
856
SYNC_CALL (write , nullptr , fd, &uvbuf, 1 , pos)
836
- if (must_free )
857
+ if (ownership == FSReqWrap::MOVE )
837
858
delete[] buf;
838
859
return args.GetReturnValue ().Set (SYNC_RESULT);
839
860
}
840
861
841
862
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 );
843
864
int err = uv_fs_write (env->event_loop (),
844
865
&req_wrap->req_ ,
845
866
fd,
0 commit comments