1919// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2020// USE OR OTHER DEALINGS IN THE SOFTWARE.
2121
22- #include < node.h>
23- #include < node_file.h>
24- #include < node_buffer.h>
22+ #include " node.h"
23+ #include " node_file.h"
24+ #include " node_buffer.h"
2525#ifdef __POSIX__
26- # include < node_stat_watcher.h>
26+ # include " node_stat_watcher.h"
2727#endif
28+ #include " req_wrap.h"
2829
2930#include < fcntl.h>
3031#include < sys/types.h>
@@ -48,9 +49,12 @@ using namespace v8;
4849#define THROW_BAD_ARGS \
4950 ThrowException (Exception::TypeError(String::New(" Bad argument" )))
5051
52+ typedef class ReqWrap <uv_fs_t > FSReqWrap;
53+
5154static Persistent<String> encoding_symbol;
5255static Persistent<String> errno_symbol;
5356static Persistent<String> buf_symbol;
57+ static Persistent<String> callback_sym;
5458
5559static inline bool SetCloseOnExec (int fd) {
5660#ifdef __POSIX__
@@ -71,8 +75,11 @@ static inline int IsInt64(double x) {
7175static void After (uv_fs_t *req) {
7276 HandleScope scope;
7377
74- Persistent<Function> *callback = cb_unwrap (req->data );
75-
78+ FSReqWrap* req_wrap = (FSReqWrap*) req->data ;
79+ assert (&req_wrap->req_ == req);
80+ Local<Value> callback_v = req_wrap->object_ ->Get (callback_sym);
81+ assert (callback_v->IsFunction ());
82+ Local<Function> callback = Local<Function>::Cast (callback_v);
7683
7784 // there is always at least one argument. "error"
7885 int argc = 1 ;
@@ -185,19 +192,18 @@ static void After(uv_fs_t *req) {
185192
186193 TryCatch try_catch;
187194
188- (* callback) ->Call (v8::Context::GetCurrent ()->Global (), argc, argv);
195+ callback->Call (v8::Context::GetCurrent ()->Global (), argc, argv);
189196
190197 if (try_catch.HasCaught ()) {
191198 FatalException (try_catch);
192199 }
193200
194- // Dispose of the persistent handle
195- cb_destroy (callback);
196-
197- uv_fs_req_cleanup (req);
198- delete req;
201+ uv_fs_req_cleanup (&req_wrap->req_ );
202+ delete req_wrap;
199203}
200204
205+ // This struct is only used on sync fs calls.
206+ // For async calls FSReqWrap is used.
201207struct fs_req_wrap {
202208 fs_req_wrap () {}
203209 ~fs_req_wrap () { uv_fs_req_cleanup (&req); }
@@ -208,11 +214,13 @@ struct fs_req_wrap {
208214};
209215
210216#define ASYNC_CALL (func, callback, ...) \
211- uv_fs_t * req = new uv_fs_t (); \
212- int r = uv_fs_##func(uv_default_loop(), req, __VA_ARGS__, After); \
217+ FSReqWrap* req_wrap = new FSReqWrap(); \
218+ int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
219+ __VA_ARGS__, After); \
213220 assert (r == 0 ); \
214- req->data = cb_persist(callback); \
215- return Undefined();
221+ req_wrap->object_->Set (callback_sym, callback); \
222+ req_wrap->Dispatched (); \
223+ return scope.Close(req_wrap->object_);
216224
217225#define SYNC_CALL (func, path, ...) \
218226 fs_req_wrap req_wrap; \
@@ -983,6 +991,8 @@ void InitFs(Handle<Object> target) {
983991 stats_constructor_template->GetFunction ());
984992 File::Initialize (target);
985993
994+ callback_sym = NODE_PSYMBOL (" callback" );
995+
986996#ifdef __POSIX__
987997 StatWatcher::Initialize (target);
988998#endif
0 commit comments