@@ -323,17 +323,12 @@ static void Close(const FunctionCallbackInfo<Value>& args) {
323
323
}
324
324
325
325
326
- Local<Object > BuildStatsObject (Environment* env, const uv_stat_t * s) {
326
+ Local<Value > BuildStatsObject (Environment* env, const uv_stat_t * s) {
327
327
// If you hit this assertion, you forgot to enter the v8::Context first.
328
328
assert (env->context () == env->isolate ()->GetCurrentContext ());
329
329
330
330
EscapableHandleScope handle_scope (env->isolate ());
331
331
332
- Local<Object> stats = env->stats_constructor_function ()->NewInstance ();
333
- if (stats.IsEmpty ()) {
334
- return handle_scope.Escape (Local<Object>());
335
- }
336
-
337
332
// The code below is very nasty-looking but it prevents a segmentation fault
338
333
// when people run JS code like the snippet below. It's apparently more
339
334
// common than you would expect, several people have reported this crash...
@@ -345,13 +340,13 @@ Local<Object> BuildStatsObject(Environment* env, const uv_stat_t* s) {
345
340
//
346
341
// We need to check the return value of Integer::New() and Date::New()
347
342
// and make sure that we bail out when V8 returns an empty handle.
343
+
344
+ // Integers.
348
345
#define X (name ) \
349
- { \
350
- Local<Value> val = Integer::New (env->isolate (), s->st_ ##name); \
351
- if (val.IsEmpty ()) \
352
- return handle_scope.Escape (Local<Object>()); \
353
- stats->Set (env->name ## _string (), val); \
354
- }
346
+ Local<Value> name = Integer::New (env->isolate (), s->st_ ##name); \
347
+ if (name.IsEmpty ()) \
348
+ return handle_scope.Escape (Local<Object>()); \
349
+
355
350
X (dev)
356
351
X (mode)
357
352
X (nlink)
@@ -360,39 +355,67 @@ Local<Object> BuildStatsObject(Environment* env, const uv_stat_t* s) {
360
355
X (rdev)
361
356
# if defined(__POSIX__)
362
357
X (blksize)
358
+ # else
359
+ Local<Value> blksize = Undefined (env->isolate ());
363
360
# endif
364
361
#undef X
365
362
363
+ // Numbers.
366
364
#define X (name ) \
367
- { \
368
- Local<Value> val = Number::New (env->isolate (), \
369
- static_cast <double >(s->st_ ##name)); \
370
- if (val.IsEmpty ()) \
371
- return handle_scope.Escape (Local<Object>()); \
372
- stats->Set (env->name ## _string (), val); \
373
- }
365
+ Local<Value> name = Number::New (env->isolate (), \
366
+ static_cast <double >(s->st_ ##name)); \
367
+ if (name.IsEmpty ()) \
368
+ return handle_scope.Escape (Local<Object>()); \
369
+
374
370
X (ino)
375
371
X (size)
376
372
# if defined(__POSIX__)
377
373
X (blocks)
374
+ # else
375
+ Local<Value> blocks = Undefined (env->isolate ());
378
376
# endif
379
377
#undef X
380
378
381
- #define X (name, rec ) \
382
- { \
383
- double msecs = static_cast <double >(s->st_ ##rec.tv_sec ) * 1000 ; \
384
- msecs += static_cast <double >(s->st_ ##rec.tv_nsec / 1000000 ); \
385
- Local<Value> val = v8::Date::New (env->isolate (), msecs); \
386
- if (val.IsEmpty ()) \
387
- return handle_scope.Escape (Local<Object>()); \
388
- stats->Set (env->name ## _string (), val); \
389
- }
390
- X (atime, atim)
391
- X (mtime, mtim)
392
- X (ctime , ctim)
393
- X (birthtime, birthtim)
379
+ // Dates.
380
+ #define X (name ) \
381
+ Local<Value> name##_msec = \
382
+ Number::New (env->isolate (), \
383
+ (static_cast <double >(s->st_ ##name.tv_sec ) * 1000 ) + \
384
+ (static_cast <double >(s->st_ ##name.tv_nsec / 1000000 ))); \
385
+ \
386
+ if (name##_msec.IsEmpty ()) \
387
+ return handle_scope.Escape (Local<Object>()); \
388
+
389
+ X (atim)
390
+ X (mtim)
391
+ X (ctim)
392
+ X (birthtim)
394
393
#undef X
395
394
395
+ // Pass stats as the first argument, this is the object we are modifying.
396
+ Local<Value> argv[] = {
397
+ dev,
398
+ mode,
399
+ nlink,
400
+ uid,
401
+ gid,
402
+ rdev,
403
+ ino,
404
+ size,
405
+ blocks,
406
+ atim_msec,
407
+ mtim_msec,
408
+ ctim_msec,
409
+ birthtim_msec
410
+ };
411
+
412
+ // Call out to JavaScript to create the stats object.
413
+ Local<Value> stats =
414
+ env->fs_stats_constructor_function ()->NewInstance (ARRAY_SIZE (argv), argv);
415
+
416
+ if (stats.IsEmpty ())
417
+ return handle_scope.Escape (Local<Object>());
418
+
396
419
return handle_scope.Escape (stats);
397
420
}
398
421
@@ -1081,18 +1104,24 @@ static void FUTimes(const FunctionCallbackInfo<Value>& args) {
1081
1104
}
1082
1105
}
1083
1106
1107
+ void FSInitialize (const FunctionCallbackInfo<Value>& args) {
1108
+ Local<Function> stats_constructor = args[0 ].As <Function>();
1109
+ assert (stats_constructor->IsFunction ());
1110
+
1111
+ Environment* env = Environment::GetCurrent (args.GetIsolate ());
1112
+ env->set_fs_stats_constructor_function (stats_constructor);
1113
+ }
1084
1114
1085
1115
void InitFs (Handle <Object> target,
1086
1116
Handle <Value> unused,
1087
1117
Handle <Context> context,
1088
1118
void * priv) {
1089
1119
Environment* env = Environment::GetCurrent (context);
1090
1120
1091
- // Initialize the stats object
1092
- Local<Function> constructor =
1093
- FunctionTemplate::New (env->isolate ())->GetFunction ();
1094
- target->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " Stats" ), constructor);
1095
- env->set_stats_constructor_function (constructor);
1121
+ // Function which creates a new Stats object.
1122
+ target->Set (
1123
+ FIXED_ONE_BYTE_STRING (env->isolate (), " FSInitialize" ),
1124
+ FunctionTemplate::New (env->isolate (), FSInitialize)->GetFunction ());
1096
1125
1097
1126
NODE_SET_METHOD (target, " close" , Close);
1098
1127
NODE_SET_METHOD (target, " open" , Open);
0 commit comments