process: allow changing `exitCode` in `on('exit')`
[platform/upstream/nodejs.git] / src / node.cc
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #include "node.h"
23 #include "node_buffer.h"
24 #include "node_constants.h"
25 #include "node_file.h"
26 #include "node_http_parser.h"
27 #include "node_javascript.h"
28 #include "node_version.h"
29
30 #if defined HAVE_PERFCTR
31 #include "node_counters.h"
32 #endif
33
34 #if HAVE_OPENSSL
35 #include "node_crypto.h"
36 #endif
37
38 #if defined HAVE_DTRACE || defined HAVE_ETW
39 #include "node_dtrace.h"
40 #endif
41
42 #include "ares.h"
43 #include "async-wrap.h"
44 #include "async-wrap-inl.h"
45 #include "env.h"
46 #include "env-inl.h"
47 #include "handle_wrap.h"
48 #include "req_wrap.h"
49 #include "string_bytes.h"
50 #include "uv.h"
51 #include "v8-debug.h"
52 #include "v8-profiler.h"
53 #include "zlib.h"
54
55 #include <assert.h>
56 #include <errno.h>
57 #include <limits.h>  // PATH_MAX
58 #include <locale.h>
59 #include <signal.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <sys/types.h>
64
65 #if defined(_MSC_VER)
66 #include <direct.h>
67 #include <io.h>
68 #include <process.h>
69 #define strcasecmp _stricmp
70 #define getpid _getpid
71 #define umask _umask
72 typedef int mode_t;
73 #else
74 #include <sys/resource.h>  // getrlimit, setrlimit
75 #include <unistd.h>  // setuid, getuid
76 #endif
77
78 #if defined(__POSIX__) && !defined(__ANDROID__)
79 #include <pwd.h>  // getpwnam()
80 #include <grp.h>  // getgrnam()
81 #endif
82
83 #ifdef __APPLE__
84 #include <crt_externs.h>
85 #define environ (*_NSGetEnviron())
86 #elif !defined(_MSC_VER)
87 extern char **environ;
88 #endif
89
90 namespace node {
91
92 using v8::Array;
93 using v8::ArrayBuffer;
94 using v8::Boolean;
95 using v8::Context;
96 using v8::Exception;
97 using v8::Function;
98 using v8::FunctionCallbackInfo;
99 using v8::FunctionTemplate;
100 using v8::Handle;
101 using v8::HandleScope;
102 using v8::HeapStatistics;
103 using v8::Integer;
104 using v8::Isolate;
105 using v8::Local;
106 using v8::Locker;
107 using v8::Message;
108 using v8::Number;
109 using v8::Object;
110 using v8::ObjectTemplate;
111 using v8::PropertyCallbackInfo;
112 using v8::String;
113 using v8::ThrowException;
114 using v8::TryCatch;
115 using v8::Uint32;
116 using v8::V8;
117 using v8::Value;
118 using v8::kExternalUnsignedIntArray;
119
120 // FIXME(bnoordhuis) Make these per-context?
121 QUEUE handle_wrap_queue = { &handle_wrap_queue, &handle_wrap_queue };
122 QUEUE req_wrap_queue = { &req_wrap_queue, &req_wrap_queue };
123
124 static bool print_eval = false;
125 static bool force_repl = false;
126 static bool trace_deprecation = false;
127 static bool throw_deprecation = false;
128 static const char* eval_string = NULL;
129 static bool use_debug_agent = false;
130 static bool debug_wait_connect = false;
131 static int debug_port = 5858;
132 static bool v8_is_profiling = false;
133 static node_module* modpending;
134 static node_module* modlist_builtin;
135 static node_module* modlist_addon;
136
137 // used by C++ modules as well
138 bool no_deprecation = false;
139
140 // process-relative uptime base, initialized at start-up
141 static double prog_start_time;
142 static bool debugger_running;
143 static uv_async_t dispatch_debug_messages_async;
144
145 // Declared in node_internals.h
146 Isolate* node_isolate = NULL;
147
148
149 class ArrayBufferAllocator : public ArrayBuffer::Allocator {
150  public:
151   // Impose an upper limit to avoid out of memory errors that bring down
152   // the process.
153   static const size_t kMaxLength = 0x3fffffff;
154   static ArrayBufferAllocator the_singleton;
155   virtual ~ArrayBufferAllocator() {}
156   virtual void* Allocate(size_t length);
157   virtual void* AllocateUninitialized(size_t length);
158   virtual void Free(void* data, size_t length);
159  private:
160   ArrayBufferAllocator() {}
161   ArrayBufferAllocator(const ArrayBufferAllocator&);
162   void operator=(const ArrayBufferAllocator&);
163 };
164
165 ArrayBufferAllocator ArrayBufferAllocator::the_singleton;
166
167
168 void* ArrayBufferAllocator::Allocate(size_t length) {
169   if (length > kMaxLength)
170     return NULL;
171   char* data = new char[length];
172   memset(data, 0, length);
173   return data;
174 }
175
176
177 void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
178   if (length > kMaxLength)
179     return NULL;
180   return new char[length];
181 }
182
183
184 void ArrayBufferAllocator::Free(void* data, size_t length) {
185   delete[] static_cast<char*>(data);
186 }
187
188
189 static void CheckImmediate(uv_check_t* handle, int status) {
190   HandleScope scope(node_isolate);
191   Environment* env = Environment::from_immediate_check_handle(handle);
192   Context::Scope context_scope(env->context());
193   MakeCallback(env, env->process_object(), env->immediate_callback_string());
194 }
195
196
197 static void IdleImmediateDummy(uv_idle_t*, int) {
198   // Do nothing. Only for maintaining event loop.
199   // TODO(bnoordhuis) Maybe make libuv accept NULL idle callbacks.
200 }
201
202
203 static inline const char *errno_string(int errorno) {
204 #define ERRNO_CASE(e)  case e: return #e;
205   switch (errorno) {
206 #ifdef EACCES
207   ERRNO_CASE(EACCES);
208 #endif
209
210 #ifdef EADDRINUSE
211   ERRNO_CASE(EADDRINUSE);
212 #endif
213
214 #ifdef EADDRNOTAVAIL
215   ERRNO_CASE(EADDRNOTAVAIL);
216 #endif
217
218 #ifdef EAFNOSUPPORT
219   ERRNO_CASE(EAFNOSUPPORT);
220 #endif
221
222 #ifdef EAGAIN
223   ERRNO_CASE(EAGAIN);
224 #endif
225
226 #ifdef EWOULDBLOCK
227 # if EAGAIN != EWOULDBLOCK
228   ERRNO_CASE(EWOULDBLOCK);
229 # endif
230 #endif
231
232 #ifdef EALREADY
233   ERRNO_CASE(EALREADY);
234 #endif
235
236 #ifdef EBADF
237   ERRNO_CASE(EBADF);
238 #endif
239
240 #ifdef EBADMSG
241   ERRNO_CASE(EBADMSG);
242 #endif
243
244 #ifdef EBUSY
245   ERRNO_CASE(EBUSY);
246 #endif
247
248 #ifdef ECANCELED
249   ERRNO_CASE(ECANCELED);
250 #endif
251
252 #ifdef ECHILD
253   ERRNO_CASE(ECHILD);
254 #endif
255
256 #ifdef ECONNABORTED
257   ERRNO_CASE(ECONNABORTED);
258 #endif
259
260 #ifdef ECONNREFUSED
261   ERRNO_CASE(ECONNREFUSED);
262 #endif
263
264 #ifdef ECONNRESET
265   ERRNO_CASE(ECONNRESET);
266 #endif
267
268 #ifdef EDEADLK
269   ERRNO_CASE(EDEADLK);
270 #endif
271
272 #ifdef EDESTADDRREQ
273   ERRNO_CASE(EDESTADDRREQ);
274 #endif
275
276 #ifdef EDOM
277   ERRNO_CASE(EDOM);
278 #endif
279
280 #ifdef EDQUOT
281   ERRNO_CASE(EDQUOT);
282 #endif
283
284 #ifdef EEXIST
285   ERRNO_CASE(EEXIST);
286 #endif
287
288 #ifdef EFAULT
289   ERRNO_CASE(EFAULT);
290 #endif
291
292 #ifdef EFBIG
293   ERRNO_CASE(EFBIG);
294 #endif
295
296 #ifdef EHOSTUNREACH
297   ERRNO_CASE(EHOSTUNREACH);
298 #endif
299
300 #ifdef EIDRM
301   ERRNO_CASE(EIDRM);
302 #endif
303
304 #ifdef EILSEQ
305   ERRNO_CASE(EILSEQ);
306 #endif
307
308 #ifdef EINPROGRESS
309   ERRNO_CASE(EINPROGRESS);
310 #endif
311
312 #ifdef EINTR
313   ERRNO_CASE(EINTR);
314 #endif
315
316 #ifdef EINVAL
317   ERRNO_CASE(EINVAL);
318 #endif
319
320 #ifdef EIO
321   ERRNO_CASE(EIO);
322 #endif
323
324 #ifdef EISCONN
325   ERRNO_CASE(EISCONN);
326 #endif
327
328 #ifdef EISDIR
329   ERRNO_CASE(EISDIR);
330 #endif
331
332 #ifdef ELOOP
333   ERRNO_CASE(ELOOP);
334 #endif
335
336 #ifdef EMFILE
337   ERRNO_CASE(EMFILE);
338 #endif
339
340 #ifdef EMLINK
341   ERRNO_CASE(EMLINK);
342 #endif
343
344 #ifdef EMSGSIZE
345   ERRNO_CASE(EMSGSIZE);
346 #endif
347
348 #ifdef EMULTIHOP
349   ERRNO_CASE(EMULTIHOP);
350 #endif
351
352 #ifdef ENAMETOOLONG
353   ERRNO_CASE(ENAMETOOLONG);
354 #endif
355
356 #ifdef ENETDOWN
357   ERRNO_CASE(ENETDOWN);
358 #endif
359
360 #ifdef ENETRESET
361   ERRNO_CASE(ENETRESET);
362 #endif
363
364 #ifdef ENETUNREACH
365   ERRNO_CASE(ENETUNREACH);
366 #endif
367
368 #ifdef ENFILE
369   ERRNO_CASE(ENFILE);
370 #endif
371
372 #ifdef ENOBUFS
373   ERRNO_CASE(ENOBUFS);
374 #endif
375
376 #ifdef ENODATA
377   ERRNO_CASE(ENODATA);
378 #endif
379
380 #ifdef ENODEV
381   ERRNO_CASE(ENODEV);
382 #endif
383
384 #ifdef ENOENT
385   ERRNO_CASE(ENOENT);
386 #endif
387
388 #ifdef ENOEXEC
389   ERRNO_CASE(ENOEXEC);
390 #endif
391
392 #ifdef ENOLINK
393   ERRNO_CASE(ENOLINK);
394 #endif
395
396 #ifdef ENOLCK
397 # if ENOLINK != ENOLCK
398   ERRNO_CASE(ENOLCK);
399 # endif
400 #endif
401
402 #ifdef ENOMEM
403   ERRNO_CASE(ENOMEM);
404 #endif
405
406 #ifdef ENOMSG
407   ERRNO_CASE(ENOMSG);
408 #endif
409
410 #ifdef ENOPROTOOPT
411   ERRNO_CASE(ENOPROTOOPT);
412 #endif
413
414 #ifdef ENOSPC
415   ERRNO_CASE(ENOSPC);
416 #endif
417
418 #ifdef ENOSR
419   ERRNO_CASE(ENOSR);
420 #endif
421
422 #ifdef ENOSTR
423   ERRNO_CASE(ENOSTR);
424 #endif
425
426 #ifdef ENOSYS
427   ERRNO_CASE(ENOSYS);
428 #endif
429
430 #ifdef ENOTCONN
431   ERRNO_CASE(ENOTCONN);
432 #endif
433
434 #ifdef ENOTDIR
435   ERRNO_CASE(ENOTDIR);
436 #endif
437
438 #ifdef ENOTEMPTY
439   ERRNO_CASE(ENOTEMPTY);
440 #endif
441
442 #ifdef ENOTSOCK
443   ERRNO_CASE(ENOTSOCK);
444 #endif
445
446 #ifdef ENOTSUP
447   ERRNO_CASE(ENOTSUP);
448 #else
449 # ifdef EOPNOTSUPP
450   ERRNO_CASE(EOPNOTSUPP);
451 # endif
452 #endif
453
454 #ifdef ENOTTY
455   ERRNO_CASE(ENOTTY);
456 #endif
457
458 #ifdef ENXIO
459   ERRNO_CASE(ENXIO);
460 #endif
461
462
463 #ifdef EOVERFLOW
464   ERRNO_CASE(EOVERFLOW);
465 #endif
466
467 #ifdef EPERM
468   ERRNO_CASE(EPERM);
469 #endif
470
471 #ifdef EPIPE
472   ERRNO_CASE(EPIPE);
473 #endif
474
475 #ifdef EPROTO
476   ERRNO_CASE(EPROTO);
477 #endif
478
479 #ifdef EPROTONOSUPPORT
480   ERRNO_CASE(EPROTONOSUPPORT);
481 #endif
482
483 #ifdef EPROTOTYPE
484   ERRNO_CASE(EPROTOTYPE);
485 #endif
486
487 #ifdef ERANGE
488   ERRNO_CASE(ERANGE);
489 #endif
490
491 #ifdef EROFS
492   ERRNO_CASE(EROFS);
493 #endif
494
495 #ifdef ESPIPE
496   ERRNO_CASE(ESPIPE);
497 #endif
498
499 #ifdef ESRCH
500   ERRNO_CASE(ESRCH);
501 #endif
502
503 #ifdef ESTALE
504   ERRNO_CASE(ESTALE);
505 #endif
506
507 #ifdef ETIME
508   ERRNO_CASE(ETIME);
509 #endif
510
511 #ifdef ETIMEDOUT
512   ERRNO_CASE(ETIMEDOUT);
513 #endif
514
515 #ifdef ETXTBSY
516   ERRNO_CASE(ETXTBSY);
517 #endif
518
519 #ifdef EXDEV
520   ERRNO_CASE(EXDEV);
521 #endif
522
523   default: return "";
524   }
525 }
526
527 const char *signo_string(int signo) {
528 #define SIGNO_CASE(e)  case e: return #e;
529   switch (signo) {
530 #ifdef SIGHUP
531   SIGNO_CASE(SIGHUP);
532 #endif
533
534 #ifdef SIGINT
535   SIGNO_CASE(SIGINT);
536 #endif
537
538 #ifdef SIGQUIT
539   SIGNO_CASE(SIGQUIT);
540 #endif
541
542 #ifdef SIGILL
543   SIGNO_CASE(SIGILL);
544 #endif
545
546 #ifdef SIGTRAP
547   SIGNO_CASE(SIGTRAP);
548 #endif
549
550 #ifdef SIGABRT
551   SIGNO_CASE(SIGABRT);
552 #endif
553
554 #ifdef SIGIOT
555 # if SIGABRT != SIGIOT
556   SIGNO_CASE(SIGIOT);
557 # endif
558 #endif
559
560 #ifdef SIGBUS
561   SIGNO_CASE(SIGBUS);
562 #endif
563
564 #ifdef SIGFPE
565   SIGNO_CASE(SIGFPE);
566 #endif
567
568 #ifdef SIGKILL
569   SIGNO_CASE(SIGKILL);
570 #endif
571
572 #ifdef SIGUSR1
573   SIGNO_CASE(SIGUSR1);
574 #endif
575
576 #ifdef SIGSEGV
577   SIGNO_CASE(SIGSEGV);
578 #endif
579
580 #ifdef SIGUSR2
581   SIGNO_CASE(SIGUSR2);
582 #endif
583
584 #ifdef SIGPIPE
585   SIGNO_CASE(SIGPIPE);
586 #endif
587
588 #ifdef SIGALRM
589   SIGNO_CASE(SIGALRM);
590 #endif
591
592   SIGNO_CASE(SIGTERM);
593
594 #ifdef SIGCHLD
595   SIGNO_CASE(SIGCHLD);
596 #endif
597
598 #ifdef SIGSTKFLT
599   SIGNO_CASE(SIGSTKFLT);
600 #endif
601
602
603 #ifdef SIGCONT
604   SIGNO_CASE(SIGCONT);
605 #endif
606
607 #ifdef SIGSTOP
608   SIGNO_CASE(SIGSTOP);
609 #endif
610
611 #ifdef SIGTSTP
612   SIGNO_CASE(SIGTSTP);
613 #endif
614
615 #ifdef SIGBREAK
616   SIGNO_CASE(SIGBREAK);
617 #endif
618
619 #ifdef SIGTTIN
620   SIGNO_CASE(SIGTTIN);
621 #endif
622
623 #ifdef SIGTTOU
624   SIGNO_CASE(SIGTTOU);
625 #endif
626
627 #ifdef SIGURG
628   SIGNO_CASE(SIGURG);
629 #endif
630
631 #ifdef SIGXCPU
632   SIGNO_CASE(SIGXCPU);
633 #endif
634
635 #ifdef SIGXFSZ
636   SIGNO_CASE(SIGXFSZ);
637 #endif
638
639 #ifdef SIGVTALRM
640   SIGNO_CASE(SIGVTALRM);
641 #endif
642
643 #ifdef SIGPROF
644   SIGNO_CASE(SIGPROF);
645 #endif
646
647 #ifdef SIGWINCH
648   SIGNO_CASE(SIGWINCH);
649 #endif
650
651 #ifdef SIGIO
652   SIGNO_CASE(SIGIO);
653 #endif
654
655 #ifdef SIGPOLL
656 # if SIGPOLL != SIGIO
657   SIGNO_CASE(SIGPOLL);
658 # endif
659 #endif
660
661 #ifdef SIGLOST
662   SIGNO_CASE(SIGLOST);
663 #endif
664
665 #ifdef SIGPWR
666 # if SIGPWR != SIGLOST
667   SIGNO_CASE(SIGPWR);
668 # endif
669 #endif
670
671 #ifdef SIGSYS
672   SIGNO_CASE(SIGSYS);
673 #endif
674
675   default: return "";
676   }
677 }
678
679
680 Local<Value> ErrnoException(int errorno,
681                             const char *syscall,
682                             const char *msg,
683                             const char *path) {
684   Environment* env = Environment::GetCurrent(node_isolate);
685
686   Local<Value> e;
687   Local<String> estring = OneByteString(node_isolate, errno_string(errorno));
688   if (msg == NULL || msg[0] == '\0') {
689     msg = strerror(errorno);
690   }
691   Local<String> message = OneByteString(node_isolate, msg);
692
693   Local<String> cons1 =
694       String::Concat(estring, FIXED_ONE_BYTE_STRING(node_isolate, ", "));
695   Local<String> cons2 = String::Concat(cons1, message);
696
697   if (path) {
698     Local<String> cons3 =
699         String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
700     Local<String> cons4 =
701         String::Concat(cons3, String::NewFromUtf8(node_isolate, path));
702     Local<String> cons5 =
703         String::Concat(cons4, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
704     e = Exception::Error(cons5);
705   } else {
706     e = Exception::Error(cons2);
707   }
708
709   Local<Object> obj = e->ToObject();
710   obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
711   obj->Set(env->code_string(), estring);
712
713   if (path != NULL) {
714     obj->Set(env->path_string(), String::NewFromUtf8(node_isolate, path));
715   }
716
717   if (syscall != NULL) {
718     obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
719   }
720
721   return e;
722 }
723
724
725 // hack alert! copy of ErrnoException, tuned for uv errors
726 Local<Value> UVException(int errorno,
727                          const char *syscall,
728                          const char *msg,
729                          const char *path) {
730   Environment* env = Environment::GetCurrent(node_isolate);
731
732   if (!msg || !msg[0])
733     msg = uv_strerror(errorno);
734
735   Local<String> estring = OneByteString(node_isolate, uv_err_name(errorno));
736   Local<String> message = OneByteString(node_isolate, msg);
737   Local<String> cons1 =
738       String::Concat(estring, FIXED_ONE_BYTE_STRING(node_isolate, ", "));
739   Local<String> cons2 = String::Concat(cons1, message);
740
741   Local<Value> e;
742
743   Local<String> path_str;
744
745   if (path) {
746 #ifdef _WIN32
747     if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
748       path_str = String::Concat(FIXED_ONE_BYTE_STRING(node_isolate, "\\\\"),
749                                 String::NewFromUtf8(node_isolate, path + 8));
750     } else if (strncmp(path, "\\\\?\\", 4) == 0) {
751       path_str = String::NewFromUtf8(node_isolate, path + 4);
752     } else {
753       path_str = String::NewFromUtf8(node_isolate, path);
754     }
755 #else
756     path_str = String::NewFromUtf8(node_isolate, path);
757 #endif
758
759     Local<String> cons3 =
760         String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
761     Local<String> cons4 =
762         String::Concat(cons3, path_str);
763     Local<String> cons5 =
764         String::Concat(cons4, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
765     e = Exception::Error(cons5);
766   } else {
767     e = Exception::Error(cons2);
768   }
769
770   Local<Object> obj = e->ToObject();
771   // TODO(piscisaureus) errno should probably go
772   obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
773   obj->Set(env->code_string(), estring);
774
775   if (path != NULL) {
776     obj->Set(env->path_string(), path_str);
777   }
778
779   if (syscall != NULL) {
780     obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
781   }
782
783   return e;
784 }
785
786
787 #ifdef _WIN32
788 // Does about the same as strerror(),
789 // but supports all windows error messages
790 static const char *winapi_strerror(const int errorno) {
791   char *errmsg = NULL;
792
793   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
794       FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
795       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
796
797   if (errmsg) {
798     // Remove trailing newlines
799     for (int i = strlen(errmsg) - 1;
800         i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
801       errmsg[i] = '\0';
802     }
803
804     return errmsg;
805   } else {
806     // FormatMessage failed
807     return "Unknown error";
808   }
809 }
810
811
812 Local<Value> WinapiErrnoException(int errorno,
813                                   const char* syscall,
814                                   const char* msg,
815                                   const char* path) {
816   Environment* env = Environment::GetCurrent(node_isolate);
817
818   Local<Value> e;
819   if (!msg || !msg[0]) {
820     msg = winapi_strerror(errorno);
821   }
822   Local<String> message = OneByteString(node_isolate, msg);
823
824   if (path) {
825     Local<String> cons1 =
826         String::Concat(message, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
827     Local<String> cons2 =
828         String::Concat(cons1, String::NewFromUtf8(node_isolate, path));
829     Local<String> cons3 =
830         String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
831     e = Exception::Error(cons3);
832   } else {
833     e = Exception::Error(message);
834   }
835
836   Local<Object> obj = e->ToObject();
837   obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
838
839   if (path != NULL) {
840     obj->Set(env->path_string(), String::NewFromUtf8(node_isolate, path));
841   }
842
843   if (syscall != NULL) {
844     obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
845   }
846
847   return e;
848 }
849 #endif
850
851
852 void SetupAsyncListener(const FunctionCallbackInfo<Value>& args) {
853   HandleScope handle_scope(args.GetIsolate());
854   Environment* env = Environment::GetCurrent(args.GetIsolate());
855
856   assert(args[0]->IsObject());
857   assert(args[1]->IsFunction());
858   assert(args[2]->IsFunction());
859   assert(args[3]->IsFunction());
860
861   env->set_async_listener_run_function(args[1].As<Function>());
862   env->set_async_listener_load_function(args[2].As<Function>());
863   env->set_async_listener_unload_function(args[3].As<Function>());
864
865   Local<Object> async_listener_flag_obj = args[0].As<Object>();
866   Environment::AsyncListener* async_listener = env->async_listener();
867   async_listener_flag_obj->SetIndexedPropertiesToExternalArrayData(
868       async_listener->fields(),
869       kExternalUnsignedIntArray,
870       async_listener->fields_count());
871
872   // Do a little housekeeping.
873   env->process_object()->Delete(
874       FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupAsyncListener"));
875 }
876
877
878 void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
879   Environment* env = Environment::GetCurrent(args.GetIsolate());
880
881   if (env->using_domains())
882     return;
883   env->set_using_domains(true);
884
885   HandleScope scope(node_isolate);
886   Local<Object> process_object = env->process_object();
887
888   Local<String> tick_callback_function_key =
889       FIXED_ONE_BYTE_STRING(node_isolate, "_tickDomainCallback");
890   Local<Function> tick_callback_function =
891       process_object->Get(tick_callback_function_key).As<Function>();
892
893   if (!tick_callback_function->IsFunction()) {
894     fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
895     abort();
896   }
897
898   process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickCallback"),
899                       tick_callback_function);
900   env->set_tick_callback_function(tick_callback_function);
901
902   assert(args[0]->IsArray());
903   assert(args[1]->IsObject());
904
905   env->set_domain_array(args[0].As<Array>());
906
907   Local<Object> domain_flag_obj = args[1].As<Object>();
908   Environment::DomainFlag* domain_flag = env->domain_flag();
909   domain_flag_obj->SetIndexedPropertiesToExternalArrayData(
910       domain_flag->fields(),
911       kExternalUnsignedIntArray,
912       domain_flag->fields_count());
913
914   // Do a little housekeeping.
915   env->process_object()->Delete(
916       FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse"));
917 }
918
919
920 void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
921   HandleScope handle_scope(args.GetIsolate());
922   Environment* env = Environment::GetCurrent(args.GetIsolate());
923
924   assert(args[0]->IsObject());
925   assert(args[1]->IsFunction());
926
927   // Values use to cross communicate with processNextTick.
928   Local<Object> tick_info_obj = args[0].As<Object>();
929   tick_info_obj->SetIndexedPropertiesToExternalArrayData(
930       env->tick_info()->fields(),
931       kExternalUnsignedIntArray,
932       env->tick_info()->fields_count());
933
934   env->set_tick_callback_function(args[1].As<Function>());
935
936   // Do a little housekeeping.
937   env->process_object()->Delete(
938       FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick"));
939 }
940
941
942 Handle<Value> MakeDomainCallback(Environment* env,
943                                  Handle<Value> recv,
944                                  const Handle<Function> callback,
945                                  int argc,
946                                  Handle<Value> argv[]) {
947   // If you hit this assertion, you forgot to enter the v8::Context first.
948   assert(env->context() == env->isolate()->GetCurrentContext());
949
950   Local<Object> process = env->process_object();
951   Local<Object> object, domain;
952   Local<Value> domain_v;
953
954   TryCatch try_catch;
955   try_catch.SetVerbose(true);
956
957   bool has_async_queue = false;
958
959   if (recv->IsObject()) {
960     object = recv.As<Object>();
961     // TODO(trevnorris): This is sucky for performance. Fix it.
962     has_async_queue = object->Has(env->async_queue_string());
963     if (has_async_queue) {
964       env->async_listener_load_function()->Call(process, 1, &recv);
965
966       if (try_catch.HasCaught())
967         return Undefined(node_isolate);
968     }
969   }
970
971   bool has_domain = false;
972
973   if (!object.IsEmpty()) {
974     domain_v = object->Get(env->domain_string());
975     has_domain = domain_v->IsObject();
976     if (has_domain) {
977       domain = domain_v.As<Object>();
978
979       if (domain->Get(env->disposed_string())->IsTrue()) {
980         // domain has been disposed of.
981         return Undefined(node_isolate);
982       }
983
984       Local<Function> enter =
985           domain->Get(env->enter_string()).As<Function>();
986       assert(enter->IsFunction());
987       enter->Call(domain, 0, NULL);
988
989       if (try_catch.HasCaught()) {
990         return Undefined(node_isolate);
991       }
992     }
993   }
994
995   Local<Value> ret = callback->Call(recv, argc, argv);
996
997   if (try_catch.HasCaught()) {
998     return Undefined(node_isolate);
999   }
1000
1001   if (has_domain) {
1002     Local<Function> exit =
1003         domain->Get(env->exit_string()).As<Function>();
1004     assert(exit->IsFunction());
1005     exit->Call(domain, 0, NULL);
1006
1007     if (try_catch.HasCaught()) {
1008       return Undefined(node_isolate);
1009     }
1010   }
1011
1012   if (has_async_queue) {
1013     env->async_listener_unload_function()->Call(process, 1, &recv);
1014
1015     if (try_catch.HasCaught())
1016       return Undefined(node_isolate);
1017   }
1018
1019   Environment::TickInfo* tick_info = env->tick_info();
1020
1021   if (tick_info->last_threw() == 1) {
1022     tick_info->set_last_threw(0);
1023     return ret;
1024   }
1025
1026   if (tick_info->in_tick()) {
1027     return ret;
1028   }
1029
1030   if (tick_info->length() == 0) {
1031     tick_info->set_index(0);
1032     return ret;
1033   }
1034
1035   tick_info->set_in_tick(true);
1036
1037   env->tick_callback_function()->Call(process, 0, NULL);
1038
1039   tick_info->set_in_tick(false);
1040
1041   if (try_catch.HasCaught()) {
1042     tick_info->set_last_threw(true);
1043     return Undefined(node_isolate);
1044   }
1045
1046   return ret;
1047 }
1048
1049
1050 Handle<Value> MakeCallback(Environment* env,
1051                            Handle<Value> recv,
1052                            const Handle<Function> callback,
1053                            int argc,
1054                            Handle<Value> argv[]) {
1055   if (env->using_domains())
1056     return MakeDomainCallback(env, recv, callback, argc, argv);
1057
1058   // If you hit this assertion, you forgot to enter the v8::Context first.
1059   assert(env->context() == env->isolate()->GetCurrentContext());
1060
1061   Local<Object> process = env->process_object();
1062
1063   TryCatch try_catch;
1064   try_catch.SetVerbose(true);
1065
1066   // TODO(trevnorris): This is sucky for performance. Fix it.
1067   bool has_async_queue =
1068       recv->IsObject() && recv.As<Object>()->Has(env->async_queue_string());
1069   if (has_async_queue) {
1070     env->async_listener_load_function()->Call(process, 1, &recv);
1071     if (try_catch.HasCaught())
1072       return Undefined(node_isolate);
1073   }
1074
1075   Local<Value> ret = callback->Call(recv, argc, argv);
1076
1077   if (try_catch.HasCaught()) {
1078     return Undefined(node_isolate);
1079   }
1080
1081   if (has_async_queue) {
1082     env->async_listener_unload_function()->Call(process, 1, &recv);
1083
1084     if (try_catch.HasCaught())
1085       return Undefined(node_isolate);
1086   }
1087
1088   Environment::TickInfo* tick_info = env->tick_info();
1089
1090   if (tick_info->in_tick()) {
1091     return ret;
1092   }
1093
1094   if (tick_info->length() == 0) {
1095     tick_info->set_index(0);
1096     return ret;
1097   }
1098
1099   tick_info->set_in_tick(true);
1100
1101   // process nextTicks after call
1102   env->tick_callback_function()->Call(process, 0, NULL);
1103
1104   tick_info->set_in_tick(false);
1105
1106   if (try_catch.HasCaught()) {
1107     tick_info->set_last_threw(true);
1108     return Undefined(node_isolate);
1109   }
1110
1111   return ret;
1112 }
1113
1114
1115 // Internal only.
1116 Handle<Value> MakeCallback(Environment* env,
1117                            Handle<Object> recv,
1118                            uint32_t index,
1119                            int argc,
1120                            Handle<Value> argv[]) {
1121   Local<Function> callback = recv->Get(index).As<Function>();
1122   assert(callback->IsFunction());
1123
1124   return MakeCallback(env, recv.As<Value>(), callback, argc, argv);
1125 }
1126
1127
1128 Handle<Value> MakeCallback(Environment* env,
1129                            Handle<Object> recv,
1130                            Handle<String> symbol,
1131                            int argc,
1132                            Handle<Value> argv[]) {
1133   Local<Function> callback = recv->Get(symbol).As<Function>();
1134   assert(callback->IsFunction());
1135   return MakeCallback(env, recv.As<Value>(), callback, argc, argv);
1136 }
1137
1138
1139 Handle<Value> MakeCallback(Environment* env,
1140                            Handle<Object> recv,
1141                            const char* method,
1142                            int argc,
1143                            Handle<Value> argv[]) {
1144   Local<String> method_string = OneByteString(node_isolate, method);
1145   return MakeCallback(env, recv, method_string, argc, argv);
1146 }
1147
1148
1149 Handle<Value> MakeCallback(Handle<Object> recv,
1150                            const char* method,
1151                            int argc,
1152                            Handle<Value> argv[]) {
1153   HandleScope handle_scope(node_isolate);  // FIXME(bnoordhuis) Isolate-ify.
1154   Local<Context> context = recv->CreationContext();
1155   Environment* env = Environment::GetCurrent(context);
1156   Context::Scope context_scope(context);
1157   return handle_scope.Close(MakeCallback(env, recv, method, argc, argv));
1158 }
1159
1160
1161 Handle<Value> MakeCallback(Handle<Object> recv,
1162                            Handle<String> symbol,
1163                            int argc,
1164                            Handle<Value> argv[]) {
1165   HandleScope handle_scope(node_isolate);  // FIXME(bnoordhuis) Isolate-ify.
1166   Local<Context> context = recv->CreationContext();
1167   Environment* env = Environment::GetCurrent(context);
1168   Context::Scope context_scope(context);
1169   return handle_scope.Close(MakeCallback(env, recv, symbol, argc, argv));
1170 }
1171
1172
1173 Handle<Value> MakeCallback(Handle<Object> recv,
1174                            Handle<Function> callback,
1175                            int argc,
1176                            Handle<Value> argv[]) {
1177   HandleScope handle_scope(node_isolate);  // FIXME(bnoordhuis) Isolate-ify.
1178   Local<Context> context = recv->CreationContext();
1179   Environment* env = Environment::GetCurrent(context);
1180   Context::Scope context_scope(context);
1181   return handle_scope.Close(
1182       MakeCallback(env, recv.As<Value>(), callback, argc, argv));
1183 }
1184
1185
1186 Handle<Value> MakeDomainCallback(Handle<Object> recv,
1187                                  Handle<Function> callback,
1188                                  int argc,
1189                                  Handle<Value> argv[]) {
1190   Local<Context> context = recv->CreationContext();
1191   Environment* env = Environment::GetCurrent(context);
1192   Context::Scope context_scope(context);
1193   HandleScope handle_scope(env->isolate());
1194   return handle_scope.Close(
1195       MakeDomainCallback(env, recv, callback, argc, argv));
1196 }
1197
1198
1199 enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1200   HandleScope scope(node_isolate);
1201
1202   if (!encoding_v->IsString())
1203     return _default;
1204
1205   String::Utf8Value encoding(encoding_v);
1206
1207   if (strcasecmp(*encoding, "utf8") == 0) {
1208     return UTF8;
1209   } else if (strcasecmp(*encoding, "utf-8") == 0) {
1210     return UTF8;
1211   } else if (strcasecmp(*encoding, "ascii") == 0) {
1212     return ASCII;
1213   } else if (strcasecmp(*encoding, "base64") == 0) {
1214     return BASE64;
1215   } else if (strcasecmp(*encoding, "ucs2") == 0) {
1216     return UCS2;
1217   } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1218     return UCS2;
1219   } else if (strcasecmp(*encoding, "utf16le") == 0) {
1220     return UCS2;
1221   } else if (strcasecmp(*encoding, "utf-16le") == 0) {
1222     return UCS2;
1223   } else if (strcasecmp(*encoding, "binary") == 0) {
1224     return BINARY;
1225   } else if (strcasecmp(*encoding, "buffer") == 0) {
1226     return BUFFER;
1227   } else if (strcasecmp(*encoding, "hex") == 0) {
1228     return HEX;
1229   } else if (strcasecmp(*encoding, "raw") == 0) {
1230     if (!no_deprecation) {
1231       fprintf(stderr, "'raw' (array of integers) has been removed. "
1232                       "Use 'binary'.\n");
1233     }
1234     return BINARY;
1235   } else if (strcasecmp(*encoding, "raws") == 0) {
1236     if (!no_deprecation) {
1237       fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1238                       "Please update your code.\n");
1239     }
1240     return BINARY;
1241   } else {
1242     return _default;
1243   }
1244 }
1245
1246 Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1247   return StringBytes::Encode(static_cast<const char*>(buf),
1248                              len,
1249                              encoding);
1250 }
1251
1252 // Returns -1 if the handle was not valid for decoding
1253 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1254   HandleScope scope(node_isolate);
1255
1256   if (val->IsArray()) {
1257     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1258                     "Use 'binary'.\n");
1259     assert(0);
1260     return -1;
1261   }
1262
1263   return StringBytes::Size(val, encoding);
1264 }
1265
1266 #ifndef MIN
1267 # define MIN(a, b) ((a) < (b) ? (a) : (b))
1268 #endif
1269
1270 // Returns number of bytes written.
1271 ssize_t DecodeWrite(char *buf,
1272                     size_t buflen,
1273                     v8::Handle<v8::Value> val,
1274                     enum encoding encoding) {
1275   return StringBytes::Write(buf, buflen, val, encoding, NULL);
1276 }
1277
1278 void AppendExceptionLine(Environment* env,
1279                          Handle<Value> er,
1280                          Handle<Message> message) {
1281   if (message.IsEmpty())
1282     return;
1283
1284   HandleScope scope(env->isolate());
1285   Local<Object> err_obj;
1286   if (!er.IsEmpty() && er->IsObject()) {
1287     err_obj = er.As<Object>();
1288
1289     // Do it only once per message
1290     if (!err_obj->GetHiddenValue(env->processed_string()).IsEmpty())
1291       return;
1292     err_obj->SetHiddenValue(env->processed_string(), True(env->isolate()));
1293   }
1294
1295   static char arrow[1024];
1296
1297   // Print (filename):(line number): (message).
1298   String::Utf8Value filename(message->GetScriptResourceName());
1299   const char* filename_string = *filename;
1300   int linenum = message->GetLineNumber();
1301   // Print line of source code.
1302   String::Utf8Value sourceline(message->GetSourceLine());
1303   const char* sourceline_string = *sourceline;
1304
1305   // Because of how node modules work, all scripts are wrapped with a
1306   // "function (module, exports, __filename, ...) {"
1307   // to provide script local variables.
1308   //
1309   // When reporting errors on the first line of a script, this wrapper
1310   // function is leaked to the user. There used to be a hack here to
1311   // truncate off the first 62 characters, but it caused numerous other
1312   // problems when vm.runIn*Context() methods were used for non-module
1313   // code.
1314   //
1315   // If we ever decide to re-instate such a hack, the following steps
1316   // must be taken:
1317   //
1318   // 1. Pass a flag around to say "this code was wrapped"
1319   // 2. Update the stack frame output so that it is also correct.
1320   //
1321   // It would probably be simpler to add a line rather than add some
1322   // number of characters to the first line, since V8 truncates the
1323   // sourceline to 78 characters, and we end up not providing very much
1324   // useful debugging info to the user if we remove 62 characters.
1325
1326   int start = message->GetStartColumn();
1327   int end = message->GetEndColumn();
1328
1329   int off = snprintf(arrow,
1330                      sizeof(arrow),
1331                      "%s:%i\n%s\n",
1332                      filename_string,
1333                      linenum,
1334                      sourceline_string);
1335   assert(off >= 0);
1336
1337   // Print wavy underline (GetUnderline is deprecated).
1338   for (int i = 0; i < start; i++) {
1339     assert(static_cast<size_t>(off) < sizeof(arrow));
1340     arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1341   }
1342   for (int i = start; i < end; i++) {
1343     assert(static_cast<size_t>(off) < sizeof(arrow));
1344     arrow[off++] = '^';
1345   }
1346   assert(static_cast<size_t>(off) < sizeof(arrow) - 1);
1347   arrow[off++] = '\n';
1348   arrow[off] = '\0';
1349
1350   Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1351   Local<Value> msg;
1352   Local<Value> stack;
1353
1354   // Allocation failed, just print it out
1355   if (arrow_str.IsEmpty() || err_obj.IsEmpty() || !err_obj->IsNativeError())
1356     goto print;
1357
1358   msg = err_obj->Get(env->message_string());
1359   stack = err_obj->Get(env->stack_string());
1360
1361   if (msg.IsEmpty() || stack.IsEmpty())
1362     goto print;
1363
1364   err_obj->Set(env->message_string(),
1365                String::Concat(arrow_str, msg->ToString()));
1366   err_obj->Set(env->stack_string(),
1367                String::Concat(arrow_str, stack->ToString()));
1368   return;
1369
1370  print:
1371   if (env->printed_error())
1372     return;
1373   env->set_printed_error(true);
1374   uv_tty_reset_mode();
1375   fprintf(stderr, "\n%s", arrow);
1376 }
1377
1378
1379 static void ReportException(Environment* env,
1380                             Handle<Value> er,
1381                             Handle<Message> message) {
1382   HandleScope scope(env->isolate());
1383
1384   AppendExceptionLine(env, er, message);
1385
1386   Local<Value> trace_value;
1387
1388   if (er->IsUndefined() || er->IsNull())
1389     trace_value = Undefined(env->isolate());
1390   else
1391     trace_value = er->ToObject()->Get(env->stack_string());
1392
1393   String::Utf8Value trace(trace_value);
1394
1395   // range errors have a trace member set to undefined
1396   if (trace.length() > 0 && !trace_value->IsUndefined()) {
1397     fprintf(stderr, "%s\n", *trace);
1398   } else {
1399     // this really only happens for RangeErrors, since they're the only
1400     // kind that won't have all this info in the trace, or when non-Error
1401     // objects are thrown manually.
1402     Local<Value> message;
1403     Local<Value> name;
1404
1405     if (er->IsObject()) {
1406       Local<Object> err_obj = er.As<Object>();
1407       message = err_obj->Get(env->message_string());
1408       name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
1409     }
1410
1411     if (message.IsEmpty() ||
1412         message->IsUndefined() ||
1413         name.IsEmpty() ||
1414         name->IsUndefined()) {
1415       // Not an error object. Just print as-is.
1416       String::Utf8Value message(er);
1417       fprintf(stderr, "%s\n", *message);
1418     } else {
1419       String::Utf8Value name_string(name);
1420       String::Utf8Value message_string(message);
1421       fprintf(stderr, "%s: %s\n", *name_string, *message_string);
1422     }
1423   }
1424
1425   fflush(stderr);
1426 }
1427
1428
1429 static void ReportException(Environment* env, const TryCatch& try_catch) {
1430   ReportException(env, try_catch.Exception(), try_catch.Message());
1431 }
1432
1433
1434 // Executes a str within the current v8 context.
1435 static Local<Value> ExecuteString(Environment* env,
1436                                   Handle<String> source,
1437                                   Handle<Value> filename) {
1438   HandleScope scope(env->isolate());
1439   TryCatch try_catch;
1440
1441   // try_catch must be nonverbose to disable FatalException() handler,
1442   // we will handle exceptions ourself.
1443   try_catch.SetVerbose(false);
1444
1445   Local<v8::Script> script = v8::Script::Compile(source, filename);
1446   if (script.IsEmpty()) {
1447     ReportException(env, try_catch);
1448     exit(3);
1449   }
1450
1451   Local<Value> result = script->Run();
1452   if (result.IsEmpty()) {
1453     ReportException(env, try_catch);
1454     exit(4);
1455   }
1456
1457   return scope.Close(result);
1458 }
1459
1460
1461 static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1462   HandleScope scope(node_isolate);
1463
1464   Local<Array> ary = Array::New();
1465   QUEUE* q = NULL;
1466   int i = 0;
1467
1468   QUEUE_FOREACH(q, &req_wrap_queue) {
1469     ReqWrap<uv_req_t>* w = CONTAINER_OF(q, ReqWrap<uv_req_t>, req_wrap_queue_);
1470     if (w->persistent().IsEmpty())
1471       continue;
1472     ary->Set(i++, w->object());
1473   }
1474
1475   args.GetReturnValue().Set(ary);
1476 }
1477
1478
1479 // Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1480 // implemented here for consistency with GetActiveRequests().
1481 void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1482   HandleScope scope(node_isolate);
1483
1484   Local<Array> ary = Array::New();
1485   QUEUE* q = NULL;
1486   int i = 0;
1487
1488   Local<String> owner_sym = FIXED_ONE_BYTE_STRING(node_isolate, "owner");
1489
1490   QUEUE_FOREACH(q, &handle_wrap_queue) {
1491     HandleWrap* w = CONTAINER_OF(q, HandleWrap, handle_wrap_queue_);
1492     if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
1493       continue;
1494     Local<Object> object = w->object();
1495     Local<Value> owner = object->Get(owner_sym);
1496     if (owner->IsUndefined())
1497       owner = object;
1498     ary->Set(i++, owner);
1499   }
1500
1501   args.GetReturnValue().Set(ary);
1502 }
1503
1504
1505 static void Abort(const FunctionCallbackInfo<Value>& args) {
1506   abort();
1507 }
1508
1509
1510 static void Chdir(const FunctionCallbackInfo<Value>& args) {
1511   HandleScope scope(node_isolate);
1512
1513   if (args.Length() != 1 || !args[0]->IsString()) {
1514     return ThrowError("Bad argument.");  // FIXME(bnoordhuis) ThrowTypeError?
1515   }
1516
1517   String::Utf8Value path(args[0]);
1518   int err = uv_chdir(*path);
1519   if (err) {
1520     return ThrowUVException(err, "uv_chdir");
1521   }
1522 }
1523
1524
1525 static void Cwd(const FunctionCallbackInfo<Value>& args) {
1526   HandleScope scope(node_isolate);
1527 #ifdef _WIN32
1528   /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1529   char buf[MAX_PATH * 4 + 1];
1530 #else
1531   char buf[PATH_MAX + 1];
1532 #endif
1533
1534   int err = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
1535   if (err) {
1536     return ThrowUVException(err, "uv_cwd");
1537   }
1538
1539   buf[ARRAY_SIZE(buf) - 1] = '\0';
1540   Local<String> cwd = String::NewFromUtf8(node_isolate, buf);
1541
1542   args.GetReturnValue().Set(cwd);
1543 }
1544
1545
1546 static void Umask(const FunctionCallbackInfo<Value>& args) {
1547   HandleScope scope(node_isolate);
1548   uint32_t old;
1549
1550   if (args.Length() < 1 || args[0]->IsUndefined()) {
1551     old = umask(0);
1552     umask(static_cast<mode_t>(old));
1553   } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1554     return ThrowTypeError("argument must be an integer or octal string.");
1555   } else {
1556     int oct;
1557     if (args[0]->IsInt32()) {
1558       oct = args[0]->Uint32Value();
1559     } else {
1560       oct = 0;
1561       String::Utf8Value str(args[0]);
1562
1563       // Parse the octal string.
1564       for (int i = 0; i < str.length(); i++) {
1565         char c = (*str)[i];
1566         if (c > '7' || c < '0') {
1567           return ThrowTypeError("invalid octal string");
1568         }
1569         oct *= 8;
1570         oct += c - '0';
1571       }
1572     }
1573     old = umask(static_cast<mode_t>(oct));
1574   }
1575
1576   args.GetReturnValue().Set(old);
1577 }
1578
1579
1580 #if defined(__POSIX__) && !defined(__ANDROID__)
1581
1582 static const uid_t uid_not_found = static_cast<uid_t>(-1);
1583 static const gid_t gid_not_found = static_cast<gid_t>(-1);
1584
1585
1586 static uid_t uid_by_name(const char* name) {
1587   struct passwd pwd;
1588   struct passwd* pp;
1589   char buf[8192];
1590
1591   errno = 0;
1592   pp = NULL;
1593
1594   if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
1595     return pp->pw_uid;
1596   }
1597
1598   return uid_not_found;
1599 }
1600
1601
1602 static char* name_by_uid(uid_t uid) {
1603   struct passwd pwd;
1604   struct passwd* pp;
1605   char buf[8192];
1606   int rc;
1607
1608   errno = 0;
1609   pp = NULL;
1610
1611   if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1612     return strdup(pp->pw_name);
1613   }
1614
1615   if (rc == 0) {
1616     errno = ENOENT;
1617   }
1618
1619   return NULL;
1620 }
1621
1622
1623 static gid_t gid_by_name(const char* name) {
1624   struct group pwd;
1625   struct group* pp;
1626   char buf[8192];
1627
1628   errno = 0;
1629   pp = NULL;
1630
1631   if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
1632     return pp->gr_gid;
1633   }
1634
1635   return gid_not_found;
1636 }
1637
1638
1639 #if 0  // For future use.
1640 static const char* name_by_gid(gid_t gid) {
1641   struct group pwd;
1642   struct group* pp;
1643   char buf[8192];
1644   int rc;
1645
1646   errno = 0;
1647   pp = NULL;
1648
1649   if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1650     return strdup(pp->gr_name);
1651   }
1652
1653   if (rc == 0) {
1654     errno = ENOENT;
1655   }
1656
1657   return NULL;
1658 }
1659 #endif
1660
1661
1662 static uid_t uid_by_name(Handle<Value> value) {
1663   if (value->IsUint32()) {
1664     return static_cast<uid_t>(value->Uint32Value());
1665   } else {
1666     String::Utf8Value name(value);
1667     return uid_by_name(*name);
1668   }
1669 }
1670
1671
1672 static gid_t gid_by_name(Handle<Value> value) {
1673   if (value->IsUint32()) {
1674     return static_cast<gid_t>(value->Uint32Value());
1675   } else {
1676     String::Utf8Value name(value);
1677     return gid_by_name(*name);
1678   }
1679 }
1680
1681
1682 static void GetUid(const FunctionCallbackInfo<Value>& args) {
1683   // uid_t is an uint32_t on all supported platforms.
1684   args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1685 }
1686
1687
1688 static void GetGid(const FunctionCallbackInfo<Value>& args) {
1689   // gid_t is an uint32_t on all supported platforms.
1690   args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1691 }
1692
1693
1694 static void SetGid(const FunctionCallbackInfo<Value>& args) {
1695   HandleScope scope(node_isolate);
1696
1697   if (!args[0]->IsUint32() && !args[0]->IsString()) {
1698     return ThrowTypeError("setgid argument must be a number or a string");
1699   }
1700
1701   gid_t gid = gid_by_name(args[0]);
1702
1703   if (gid == gid_not_found) {
1704     return ThrowError("setgid group id does not exist");
1705   }
1706
1707   if (setgid(gid)) {
1708     return ThrowErrnoException(errno, "setgid");
1709   }
1710 }
1711
1712
1713 static void SetUid(const FunctionCallbackInfo<Value>& args) {
1714   HandleScope scope(node_isolate);
1715
1716   if (!args[0]->IsUint32() && !args[0]->IsString()) {
1717     return ThrowTypeError("setuid argument must be a number or a string");
1718   }
1719
1720   uid_t uid = uid_by_name(args[0]);
1721
1722   if (uid == uid_not_found) {
1723     return ThrowError("setuid user id does not exist");
1724   }
1725
1726   if (setuid(uid)) {
1727     return ThrowErrnoException(errno, "setuid");
1728   }
1729 }
1730
1731
1732 static void GetGroups(const FunctionCallbackInfo<Value>& args) {
1733   HandleScope scope(node_isolate);
1734
1735   int ngroups = getgroups(0, NULL);
1736
1737   if (ngroups == -1) {
1738     return ThrowErrnoException(errno, "getgroups");
1739   }
1740
1741   gid_t* groups = new gid_t[ngroups];
1742
1743   ngroups = getgroups(ngroups, groups);
1744
1745   if (ngroups == -1) {
1746     delete[] groups;
1747     return ThrowErrnoException(errno, "getgroups");
1748   }
1749
1750   Local<Array> groups_list = Array::New(ngroups);
1751   bool seen_egid = false;
1752   gid_t egid = getegid();
1753
1754   for (int i = 0; i < ngroups; i++) {
1755     groups_list->Set(i, Integer::New(groups[i], node_isolate));
1756     if (groups[i] == egid)
1757       seen_egid = true;
1758   }
1759
1760   delete[] groups;
1761
1762   if (seen_egid == false) {
1763     groups_list->Set(ngroups, Integer::New(egid, node_isolate));
1764   }
1765
1766   args.GetReturnValue().Set(groups_list);
1767 }
1768
1769
1770 static void SetGroups(const FunctionCallbackInfo<Value>& args) {
1771   HandleScope scope(node_isolate);
1772
1773   if (!args[0]->IsArray()) {
1774     return ThrowTypeError("argument 1 must be an array");
1775   }
1776
1777   Local<Array> groups_list = args[0].As<Array>();
1778   size_t size = groups_list->Length();
1779   gid_t* groups = new gid_t[size];
1780
1781   for (size_t i = 0; i < size; i++) {
1782     gid_t gid = gid_by_name(groups_list->Get(i));
1783
1784     if (gid == gid_not_found) {
1785       delete[] groups;
1786       return ThrowError("group name not found");
1787     }
1788
1789     groups[i] = gid;
1790   }
1791
1792   int rc = setgroups(size, groups);
1793   delete[] groups;
1794
1795   if (rc == -1) {
1796     return ThrowErrnoException(errno, "setgroups");
1797   }
1798 }
1799
1800
1801 static void InitGroups(const FunctionCallbackInfo<Value>& args) {
1802   HandleScope scope(node_isolate);
1803
1804   if (!args[0]->IsUint32() && !args[0]->IsString()) {
1805     return ThrowTypeError("argument 1 must be a number or a string");
1806   }
1807
1808   if (!args[1]->IsUint32() && !args[1]->IsString()) {
1809     return ThrowTypeError("argument 2 must be a number or a string");
1810   }
1811
1812   String::Utf8Value arg0(args[0]);
1813   gid_t extra_group;
1814   bool must_free;
1815   char* user;
1816
1817   if (args[0]->IsUint32()) {
1818     user = name_by_uid(args[0]->Uint32Value());
1819     must_free = true;
1820   } else {
1821     user = *arg0;
1822     must_free = false;
1823   }
1824
1825   if (user == NULL) {
1826     return ThrowError("initgroups user not found");
1827   }
1828
1829   extra_group = gid_by_name(args[1]);
1830
1831   if (extra_group == gid_not_found) {
1832     if (must_free)
1833       free(user);
1834     return ThrowError("initgroups extra group not found");
1835   }
1836
1837   int rc = initgroups(user, extra_group);
1838
1839   if (must_free) {
1840     free(user);
1841   }
1842
1843   if (rc) {
1844     return ThrowErrnoException(errno, "initgroups");
1845   }
1846 }
1847
1848 #endif  // __POSIX__ && !defined(__ANDROID__)
1849
1850
1851 void Exit(const FunctionCallbackInfo<Value>& args) {
1852   HandleScope scope(node_isolate);
1853   exit(args[0]->IntegerValue());
1854 }
1855
1856
1857 static void Uptime(const FunctionCallbackInfo<Value>& args) {
1858   HandleScope scope(node_isolate);
1859   double uptime;
1860   if (uv_uptime(&uptime))
1861     return;
1862   args.GetReturnValue().Set(uptime - prog_start_time);
1863 }
1864
1865
1866 void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
1867   HandleScope handle_scope(args.GetIsolate());
1868   Environment* env = Environment::GetCurrent(args.GetIsolate());
1869
1870   size_t rss;
1871   int err = uv_resident_set_memory(&rss);
1872   if (err) {
1873     return ThrowUVException(err, "uv_resident_set_memory");
1874   }
1875
1876   // V8 memory usage
1877   HeapStatistics v8_heap_stats;
1878   node_isolate->GetHeapStatistics(&v8_heap_stats);
1879
1880   Local<Integer> heap_total =
1881       Integer::NewFromUnsigned(v8_heap_stats.total_heap_size(), node_isolate);
1882   Local<Integer> heap_used =
1883       Integer::NewFromUnsigned(v8_heap_stats.used_heap_size(), node_isolate);
1884
1885   Local<Object> info = Object::New();
1886   info->Set(env->rss_string(), Number::New(node_isolate, rss));
1887   info->Set(env->heap_total_string(), heap_total);
1888   info->Set(env->heap_used_string(), heap_used);
1889
1890   args.GetReturnValue().Set(info);
1891 }
1892
1893
1894 void Kill(const FunctionCallbackInfo<Value>& args) {
1895   HandleScope scope(node_isolate);
1896
1897   if (args.Length() != 2) {
1898     return ThrowError("Bad argument.");
1899   }
1900
1901   int pid = args[0]->IntegerValue();
1902   int sig = args[1]->Int32Value();
1903   int err = uv_kill(pid, sig);
1904   args.GetReturnValue().Set(err);
1905 }
1906
1907 // used in Hrtime() below
1908 #define NANOS_PER_SEC 1000000000
1909
1910 // Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1911 // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1912 // so this function instead returns an Array with 2 entries representing seconds
1913 // and nanoseconds, to avoid any integer overflow possibility.
1914 // Pass in an Array from a previous hrtime() call to instead get a time diff.
1915 void Hrtime(const FunctionCallbackInfo<Value>& args) {
1916   HandleScope scope(node_isolate);
1917
1918   uint64_t t = uv_hrtime();
1919
1920   if (args.Length() > 0) {
1921     // return a time diff tuple
1922     if (!args[0]->IsArray()) {
1923       return ThrowTypeError("process.hrtime() only accepts an Array tuple.");
1924     }
1925     Local<Array> inArray = Local<Array>::Cast(args[0]);
1926     uint64_t seconds = inArray->Get(0)->Uint32Value();
1927     uint64_t nanos = inArray->Get(1)->Uint32Value();
1928     t -= (seconds * NANOS_PER_SEC) + nanos;
1929   }
1930
1931   Local<Array> tuple = Array::New(2);
1932   tuple->Set(0, Integer::NewFromUnsigned(t / NANOS_PER_SEC, node_isolate));
1933   tuple->Set(1, Integer::NewFromUnsigned(t % NANOS_PER_SEC, node_isolate));
1934   args.GetReturnValue().Set(tuple);
1935 }
1936
1937 extern "C" void node_module_register(void* m) {
1938   struct node_module* mp = reinterpret_cast<struct node_module*>(m);
1939
1940   if (mp->nm_flags & NM_F_BUILTIN) {
1941     mp->nm_link = modlist_builtin;
1942     modlist_builtin = mp;
1943   } else {
1944     assert(modpending == NULL);
1945     modpending = mp;
1946   }
1947 }
1948
1949 struct node_module* get_builtin_module(const char* name) {
1950   struct node_module* mp;
1951
1952   for (mp = modlist_builtin; mp != NULL; mp = mp->nm_link) {
1953     if (strcmp(mp->nm_modname, name) == 0)
1954       break;
1955   }
1956
1957   assert(mp == NULL || (mp->nm_flags & NM_F_BUILTIN) != 0);
1958   return (mp);
1959 }
1960
1961 typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
1962
1963 // DLOpen is process.dlopen(module, filename).
1964 // Used to load 'module.node' dynamically shared objects.
1965 //
1966 // FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
1967 // when two contexts try to load the same shared object. Maybe have a shadow
1968 // cache that's a plain C list or hash table that's shared across contexts?
1969 void DLOpen(const FunctionCallbackInfo<Value>& args) {
1970   HandleScope handle_scope(args.GetIsolate());
1971   Environment* env = Environment::GetCurrent(args.GetIsolate());
1972   struct node_module* mp;
1973   uv_lib_t lib;
1974
1975   if (args.Length() < 2) {
1976     ThrowError("process.dlopen takes exactly 2 arguments.");
1977     return;
1978   }
1979
1980   Local<Object> module = args[0]->ToObject();  // Cast
1981   String::Utf8Value filename(args[1]);  // Cast
1982
1983   Local<String> exports_string = env->exports_string();
1984   Local<Object> exports = module->Get(exports_string)->ToObject();
1985
1986   if (uv_dlopen(*filename, &lib)) {
1987     Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
1988 #ifdef _WIN32
1989     // Windows needs to add the filename into the error message
1990     errmsg = String::Concat(errmsg, args[1]->ToString());
1991 #endif  // _WIN32
1992     ThrowException(Exception::Error(errmsg));
1993     return;
1994   }
1995
1996   /*
1997    * Objects containing v14 or later modules will have registered themselves
1998    * on the pending list.  Activate all of them now.  At present, only one
1999    * module per object is supported.
2000    */
2001   mp = modpending;
2002   modpending = NULL;
2003
2004   if (mp == NULL) {
2005     ThrowError("Module did not self-register.");
2006     return;
2007   }
2008   if (mp->nm_version != NODE_MODULE_VERSION) {
2009     char errmsg[1024];
2010     snprintf(errmsg,
2011              sizeof(errmsg),
2012              "Module version mismatch. Expected %d, got %d.",
2013              NODE_MODULE_VERSION, mp->nm_version);
2014     ThrowError(errmsg);
2015     return;
2016   }
2017   if (mp->nm_flags & NM_F_BUILTIN) {
2018     ThrowError("Built-in module self-registered.");
2019     return;
2020   }
2021
2022   mp->nm_dso_handle = lib.handle;
2023   mp->nm_link = modlist_addon;
2024   modlist_addon = mp;
2025
2026   if (mp->nm_context_register_func != NULL) {
2027     mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2028   } else if (mp->nm_register_func != NULL) {
2029     mp->nm_register_func(exports, module, mp->nm_priv);
2030   } else {
2031     ThrowError("Module has no declared entry point.");
2032     return;
2033   }
2034
2035   // Tell coverity that 'handle' should not be freed when we return.
2036   // coverity[leaked_storage]
2037 }
2038
2039
2040 static void OnFatalError(const char* location, const char* message) {
2041   if (location) {
2042     fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
2043   } else {
2044     fprintf(stderr, "FATAL ERROR: %s\n", message);
2045   }
2046   fflush(stderr);
2047   abort();
2048 }
2049
2050
2051 NO_RETURN void FatalError(const char* location, const char* message) {
2052   OnFatalError(location, message);
2053   // to supress compiler warning
2054   abort();
2055 }
2056
2057
2058 void FatalException(Handle<Value> error, Handle<Message> message) {
2059   HandleScope scope(node_isolate);
2060
2061   Environment* env = Environment::GetCurrent(node_isolate);
2062   Local<Object> process_object = env->process_object();
2063   Local<String> fatal_exception_string = env->fatal_exception_string();
2064   Local<Function> fatal_exception_function =
2065       process_object->Get(fatal_exception_string).As<Function>();
2066
2067   if (!fatal_exception_function->IsFunction()) {
2068     // failed before the process._fatalException function was added!
2069     // this is probably pretty bad.  Nothing to do but report and exit.
2070     ReportException(env, error, message);
2071     exit(6);
2072   }
2073
2074   TryCatch fatal_try_catch;
2075
2076   // Do not call FatalException when _fatalException handler throws
2077   fatal_try_catch.SetVerbose(false);
2078
2079   // this will return true if the JS layer handled it, false otherwise
2080   Local<Value> caught =
2081       fatal_exception_function->Call(process_object, 1, &error);
2082
2083   if (fatal_try_catch.HasCaught()) {
2084     // the fatal exception function threw, so we must exit
2085     ReportException(env, fatal_try_catch);
2086     exit(7);
2087   }
2088
2089   if (false == caught->BooleanValue()) {
2090     ReportException(env, error, message);
2091     exit(1);
2092   }
2093 }
2094
2095
2096 void FatalException(const TryCatch& try_catch) {
2097   HandleScope scope(node_isolate);
2098   // TODO(bajtos) do not call FatalException if try_catch is verbose
2099   // (requires V8 API to expose getter for try_catch.is_verbose_)
2100   FatalException(try_catch.Exception(), try_catch.Message());
2101 }
2102
2103
2104 void OnMessage(Handle<Message> message, Handle<Value> error) {
2105   // The current version of V8 sends messages for errors only
2106   // (thus `error` is always set).
2107   FatalException(error, message);
2108 }
2109
2110
2111 static void Binding(const FunctionCallbackInfo<Value>& args) {
2112   HandleScope handle_scope(args.GetIsolate());
2113   Environment* env = Environment::GetCurrent(args.GetIsolate());
2114
2115   Local<String> module = args[0]->ToString();
2116   String::Utf8Value module_v(module);
2117
2118   Local<Object> cache = env->binding_cache_object();
2119   Local<Object> exports;
2120
2121   if (cache->Has(module)) {
2122     exports = cache->Get(module)->ToObject();
2123     args.GetReturnValue().Set(exports);
2124     return;
2125   }
2126
2127   // Append a string to process.moduleLoadList
2128   char buf[1024];
2129   snprintf(buf, sizeof(buf), "Binding %s", *module_v);
2130
2131   Local<Array> modules = env->module_load_list_array();
2132   uint32_t l = modules->Length();
2133   modules->Set(l, OneByteString(node_isolate, buf));
2134
2135   node_module* mod = get_builtin_module(*module_v);
2136   if (mod != NULL) {
2137     exports = Object::New();
2138     // Internal bindings don't have a "module" object, only exports.
2139     assert(mod->nm_register_func == NULL);
2140     assert(mod->nm_context_register_func != NULL);
2141     Local<Value> unused = Undefined(env->isolate());
2142     mod->nm_context_register_func(exports, unused,
2143       env->context(), mod->nm_priv);
2144     cache->Set(module, exports);
2145   } else if (!strcmp(*module_v, "constants")) {
2146     exports = Object::New();
2147     DefineConstants(exports);
2148     cache->Set(module, exports);
2149   } else if (!strcmp(*module_v, "natives")) {
2150     exports = Object::New();
2151     DefineJavaScript(exports);
2152     cache->Set(module, exports);
2153   } else {
2154     return ThrowError("No such module");
2155   }
2156
2157   args.GetReturnValue().Set(exports);
2158 }
2159
2160
2161 static void ProcessTitleGetter(Local<String> property,
2162                                const PropertyCallbackInfo<Value>& info) {
2163   HandleScope scope(node_isolate);
2164   char buffer[512];
2165   uv_get_process_title(buffer, sizeof(buffer));
2166   info.GetReturnValue().Set(String::NewFromUtf8(node_isolate, buffer));
2167 }
2168
2169
2170 static void ProcessTitleSetter(Local<String> property,
2171                                Local<Value> value,
2172                                const PropertyCallbackInfo<void>& info) {
2173   HandleScope scope(node_isolate);
2174   String::Utf8Value title(value);
2175   // TODO(piscisaureus): protect with a lock
2176   uv_set_process_title(*title);
2177 }
2178
2179
2180 static void EnvGetter(Local<String> property,
2181                       const PropertyCallbackInfo<Value>& info) {
2182   HandleScope scope(node_isolate);
2183 #ifdef __POSIX__
2184   String::Utf8Value key(property);
2185   const char* val = getenv(*key);
2186   if (val) {
2187     return info.GetReturnValue().Set(String::NewFromUtf8(node_isolate, val));
2188   }
2189 #else  // _WIN32
2190   String::Value key(property);
2191   WCHAR buffer[32767];  // The maximum size allowed for environment variables.
2192   DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2193                                          buffer,
2194                                          ARRAY_SIZE(buffer));
2195   // If result >= sizeof buffer the buffer was too small. That should never
2196   // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2197   // not found.
2198   if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2199       result < ARRAY_SIZE(buffer)) {
2200     const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
2201     Local<String> rc = String::NewFromTwoByte(node_isolate, two_byte_buffer);
2202     return info.GetReturnValue().Set(rc);
2203   }
2204 #endif
2205   // Not found.  Fetch from prototype.
2206   info.GetReturnValue().Set(
2207       info.Data().As<Object>()->Get(property));
2208 }
2209
2210
2211 static void EnvSetter(Local<String> property,
2212                       Local<Value> value,
2213                       const PropertyCallbackInfo<Value>& info) {
2214   HandleScope scope(node_isolate);
2215 #ifdef __POSIX__
2216   String::Utf8Value key(property);
2217   String::Utf8Value val(value);
2218   setenv(*key, *val, 1);
2219 #else  // _WIN32
2220   String::Value key(property);
2221   String::Value val(value);
2222   WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2223   // Environment variables that start with '=' are read-only.
2224   if (key_ptr[0] != L'=') {
2225     SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2226   }
2227 #endif
2228   // Whether it worked or not, always return rval.
2229   info.GetReturnValue().Set(value);
2230 }
2231
2232
2233 static void EnvQuery(Local<String> property,
2234                      const PropertyCallbackInfo<Integer>& info) {
2235   HandleScope scope(node_isolate);
2236   int32_t rc = -1;  // Not found unless proven otherwise.
2237 #ifdef __POSIX__
2238   String::Utf8Value key(property);
2239   if (getenv(*key))
2240     rc = 0;
2241 #else  // _WIN32
2242   String::Value key(property);
2243   WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2244   if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
2245       GetLastError() == ERROR_SUCCESS) {
2246     rc = 0;
2247     if (key_ptr[0] == L'=') {
2248       // Environment variables that start with '=' are hidden and read-only.
2249       rc = static_cast<int32_t>(v8::ReadOnly) |
2250            static_cast<int32_t>(v8::DontDelete) |
2251            static_cast<int32_t>(v8::DontEnum);
2252     }
2253   }
2254 #endif
2255   if (rc != -1)
2256     info.GetReturnValue().Set(rc);
2257 }
2258
2259
2260 static void EnvDeleter(Local<String> property,
2261                        const PropertyCallbackInfo<Boolean>& info) {
2262   HandleScope scope(node_isolate);
2263   bool rc = true;
2264 #ifdef __POSIX__
2265   String::Utf8Value key(property);
2266   rc = getenv(*key) != NULL;
2267   if (rc)
2268     unsetenv(*key);
2269 #else
2270   String::Value key(property);
2271   WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2272   if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
2273     // Deletion failed. Return true if the key wasn't there in the first place,
2274     // false if it is still there.
2275     rc = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
2276          GetLastError() != ERROR_SUCCESS;
2277   }
2278 #endif
2279   info.GetReturnValue().Set(rc);
2280 }
2281
2282
2283 static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2284   HandleScope scope(node_isolate);
2285 #ifdef __POSIX__
2286   int size = 0;
2287   while (environ[size])
2288     size++;
2289
2290   Local<Array> env = Array::New(size);
2291
2292   for (int i = 0; i < size; ++i) {
2293     const char* var = environ[i];
2294     const char* s = strchr(var, '=');
2295     const int length = s ? s - var : strlen(var);
2296     Local<String> name = String::NewFromUtf8(node_isolate,
2297                                              var,
2298                                              String::kNormalString,
2299                                              length);
2300     env->Set(i, name);
2301   }
2302 #else  // _WIN32
2303   WCHAR* environment = GetEnvironmentStringsW();
2304   if (environment == NULL)
2305     return;  // This should not happen.
2306   Local<Array> env = Array::New();
2307   WCHAR* p = environment;
2308   int i = 0;
2309   while (*p != NULL) {
2310     WCHAR *s;
2311     if (*p == L'=') {
2312       // If the key starts with '=' it is a hidden environment variable.
2313       p += wcslen(p) + 1;
2314       continue;
2315     } else {
2316       s = wcschr(p, L'=');
2317     }
2318     if (!s) {
2319       s = p + wcslen(p);
2320     }
2321     const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
2322     const size_t two_byte_buffer_len = s - p;
2323     Local<String> value = String::NewFromTwoByte(node_isolate,
2324                                                  two_byte_buffer,
2325                                                  String::kNormalString,
2326                                                  two_byte_buffer_len);
2327     env->Set(i++, value);
2328     p = s + wcslen(s) + 1;
2329   }
2330   FreeEnvironmentStringsW(environment);
2331 #endif
2332
2333   info.GetReturnValue().Set(env);
2334 }
2335
2336
2337 static Handle<Object> GetFeatures() {
2338   HandleScope scope(node_isolate);
2339
2340   Local<Object> obj = Object::New();
2341 #if defined(DEBUG) && DEBUG
2342   Local<Value> debug = True(node_isolate);
2343 #else
2344   Local<Value> debug = False(node_isolate);
2345 #endif  // defined(DEBUG) && DEBUG
2346
2347   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "debug"), debug);
2348
2349   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "uv"), True(node_isolate));
2350   // TODO(bnoordhuis) ping libuv
2351   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "ipv6"), True(node_isolate));
2352
2353 #ifdef OPENSSL_NPN_NEGOTIATED
2354   Local<Boolean> tls_npn = True(node_isolate);
2355 #else
2356   Local<Boolean> tls_npn = False(node_isolate);
2357 #endif
2358   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls_npn"), tls_npn);
2359
2360 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2361   Local<Boolean> tls_sni = True(node_isolate);
2362 #else
2363   Local<Boolean> tls_sni = False(node_isolate);
2364 #endif
2365   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls_sni"), tls_sni);
2366
2367   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls"),
2368            Boolean::New(get_builtin_module("crypto") != NULL));
2369
2370   return scope.Close(obj);
2371 }
2372
2373
2374 static void DebugPortGetter(Local<String> property,
2375                             const PropertyCallbackInfo<Value>& info) {
2376   HandleScope scope(node_isolate);
2377   info.GetReturnValue().Set(debug_port);
2378 }
2379
2380
2381 static void DebugPortSetter(Local<String> property,
2382                             Local<Value> value,
2383                             const PropertyCallbackInfo<void>& info) {
2384   HandleScope scope(node_isolate);
2385   debug_port = value->NumberValue();
2386 }
2387
2388
2389 static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2390 static void DebugPause(const FunctionCallbackInfo<Value>& args);
2391 static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2392
2393
2394 void NeedImmediateCallbackGetter(Local<String> property,
2395                                  const PropertyCallbackInfo<Value>& info) {
2396   HandleScope handle_scope(info.GetIsolate());
2397   Environment* env = Environment::GetCurrent(info.GetIsolate());
2398   const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2399   bool active = uv_is_active(
2400       reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2401   info.GetReturnValue().Set(active);
2402 }
2403
2404
2405 static void NeedImmediateCallbackSetter(
2406     Local<String> property,
2407     Local<Value> value,
2408     const PropertyCallbackInfo<void>& info) {
2409   HandleScope handle_scope(info.GetIsolate());
2410   Environment* env = Environment::GetCurrent(info.GetIsolate());
2411
2412   uv_check_t* immediate_check_handle = env->immediate_check_handle();
2413   bool active = uv_is_active(
2414       reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2415
2416   if (active == value->BooleanValue())
2417     return;
2418
2419   uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
2420
2421   if (active) {
2422     uv_check_stop(immediate_check_handle);
2423     uv_idle_stop(immediate_idle_handle);
2424   } else {
2425     uv_check_start(immediate_check_handle, CheckImmediate);
2426     // Idle handle is needed only to stop the event loop from blocking in poll.
2427     uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
2428   }
2429 }
2430
2431
2432 void SetIdle(uv_prepare_t* handle, int) {
2433   Environment* env = Environment::from_idle_prepare_handle(handle);
2434   env->isolate()->GetCpuProfiler()->SetIdle(true);
2435 }
2436
2437
2438 void ClearIdle(uv_check_t* handle, int) {
2439   Environment* env = Environment::from_idle_check_handle(handle);
2440   env->isolate()->GetCpuProfiler()->SetIdle(false);
2441 }
2442
2443
2444 void StartProfilerIdleNotifier(Environment* env) {
2445   uv_prepare_start(env->idle_prepare_handle(), SetIdle);
2446   uv_check_start(env->idle_check_handle(), ClearIdle);
2447 }
2448
2449
2450 void StopProfilerIdleNotifier(Environment* env) {
2451   uv_prepare_stop(env->idle_prepare_handle());
2452   uv_check_stop(env->idle_check_handle());
2453 }
2454
2455
2456 void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2457   HandleScope handle_scope(args.GetIsolate());
2458   Environment* env = Environment::GetCurrent(args.GetIsolate());
2459   StartProfilerIdleNotifier(env);
2460 }
2461
2462
2463 void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2464   HandleScope handle_scope(args.GetIsolate());
2465   Environment* env = Environment::GetCurrent(args.GetIsolate());
2466   StopProfilerIdleNotifier(env);
2467 }
2468
2469
2470 #define READONLY_PROPERTY(obj, str, var)                                      \
2471   do {                                                                        \
2472     obj->Set(OneByteString(node_isolate, str), var, v8::ReadOnly);            \
2473   } while (0)
2474
2475
2476 void SetupProcessObject(Environment* env,
2477                         int argc,
2478                         const char* const* argv,
2479                         int exec_argc,
2480                         const char* const* exec_argv) {
2481   HandleScope scope(node_isolate);
2482
2483   Local<Object> process = env->process_object();
2484
2485   process->SetAccessor(FIXED_ONE_BYTE_STRING(node_isolate, "title"),
2486                        ProcessTitleGetter,
2487                        ProcessTitleSetter);
2488
2489   // process.version
2490   READONLY_PROPERTY(process,
2491                     "version",
2492                     FIXED_ONE_BYTE_STRING(node_isolate, NODE_VERSION));
2493
2494   // process.moduleLoadList
2495   READONLY_PROPERTY(process,
2496                     "moduleLoadList",
2497                     env->module_load_list_array());
2498
2499   // process.versions
2500   Local<Object> versions = Object::New();
2501   READONLY_PROPERTY(process, "versions", versions);
2502
2503   const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2504                                      "."
2505                                      NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR);
2506   READONLY_PROPERTY(versions,
2507                     "http_parser",
2508                     FIXED_ONE_BYTE_STRING(node_isolate, http_parser_version));
2509
2510   // +1 to get rid of the leading 'v'
2511   READONLY_PROPERTY(versions,
2512                     "node",
2513                     OneByteString(node_isolate, NODE_VERSION + 1));
2514   READONLY_PROPERTY(versions,
2515                     "v8",
2516                     OneByteString(node_isolate, V8::GetVersion()));
2517   READONLY_PROPERTY(versions,
2518                     "uv",
2519                     OneByteString(node_isolate, uv_version_string()));
2520   READONLY_PROPERTY(versions,
2521                     "zlib",
2522                     FIXED_ONE_BYTE_STRING(node_isolate, ZLIB_VERSION));
2523
2524   const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
2525   READONLY_PROPERTY(versions,
2526                     "modules",
2527                     FIXED_ONE_BYTE_STRING(node_isolate, node_modules_version));
2528
2529 #if HAVE_OPENSSL
2530   // Stupid code to slice out the version string.
2531   {  // NOLINT(whitespace/braces)
2532     size_t i, j, k;
2533     int c;
2534     for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
2535       c = OPENSSL_VERSION_TEXT[i];
2536       if ('0' <= c && c <= '9') {
2537         for (j = i + 1; j < k; ++j) {
2538           c = OPENSSL_VERSION_TEXT[j];
2539           if (c == ' ')
2540             break;
2541         }
2542         break;
2543       }
2544     }
2545     READONLY_PROPERTY(
2546         versions,
2547         "openssl",
2548         OneByteString(node_isolate, &OPENSSL_VERSION_TEXT[i], j - i));
2549   }
2550 #endif
2551
2552   // process.arch
2553   READONLY_PROPERTY(process, "arch", OneByteString(node_isolate, ARCH));
2554
2555   // process.platform
2556   READONLY_PROPERTY(process,
2557                     "platform",
2558                     OneByteString(node_isolate, PLATFORM));
2559
2560   // process.argv
2561   Local<Array> arguments = Array::New(argc);
2562   for (int i = 0; i < argc; ++i) {
2563     arguments->Set(i, String::NewFromUtf8(node_isolate, argv[i]));
2564   }
2565   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "argv"), arguments);
2566
2567   // process.execArgv
2568   Local<Array> exec_arguments = Array::New(exec_argc);
2569   for (int i = 0; i < exec_argc; ++i) {
2570     exec_arguments->Set(i, String::NewFromUtf8(node_isolate, exec_argv[i]));
2571   }
2572   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "execArgv"), exec_arguments);
2573
2574   // create process.env
2575   Local<ObjectTemplate> process_env_template = ObjectTemplate::New();
2576   process_env_template->SetNamedPropertyHandler(EnvGetter,
2577                                                 EnvSetter,
2578                                                 EnvQuery,
2579                                                 EnvDeleter,
2580                                                 EnvEnumerator,
2581                                                 Object::New());
2582   Local<Object> process_env = process_env_template->NewInstance();
2583   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "env"), process_env);
2584
2585   READONLY_PROPERTY(process, "pid", Integer::New(getpid(), node_isolate));
2586   READONLY_PROPERTY(process, "features", GetFeatures());
2587   process->SetAccessor(
2588       FIXED_ONE_BYTE_STRING(node_isolate, "_needImmediateCallback"),
2589       NeedImmediateCallbackGetter,
2590       NeedImmediateCallbackSetter);
2591
2592   // -e, --eval
2593   if (eval_string) {
2594     READONLY_PROPERTY(process,
2595                       "_eval",
2596                       String::NewFromUtf8(node_isolate, eval_string));
2597   }
2598
2599   // -p, --print
2600   if (print_eval) {
2601     READONLY_PROPERTY(process, "_print_eval", True(node_isolate));
2602   }
2603
2604   // -i, --interactive
2605   if (force_repl) {
2606     READONLY_PROPERTY(process, "_forceRepl", True(node_isolate));
2607   }
2608
2609   // --no-deprecation
2610   if (no_deprecation) {
2611     READONLY_PROPERTY(process, "noDeprecation", True(node_isolate));
2612   }
2613
2614   // --throw-deprecation
2615   if (throw_deprecation) {
2616     READONLY_PROPERTY(process, "throwDeprecation", True(node_isolate));
2617   }
2618
2619   // --trace-deprecation
2620   if (trace_deprecation) {
2621     READONLY_PROPERTY(process, "traceDeprecation", True(node_isolate));
2622   }
2623
2624   size_t exec_path_len = 2 * PATH_MAX;
2625   char* exec_path = new char[exec_path_len];
2626   Local<String> exec_path_value;
2627   if (uv_exepath(exec_path, &exec_path_len) == 0) {
2628     exec_path_value = String::NewFromUtf8(node_isolate,
2629                                           exec_path,
2630                                           String::kNormalString,
2631                                           exec_path_len);
2632   } else {
2633     exec_path_value = String::NewFromUtf8(node_isolate, argv[0]);
2634   }
2635   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "execPath"),
2636                exec_path_value);
2637   delete[] exec_path;
2638
2639   process->SetAccessor(FIXED_ONE_BYTE_STRING(node_isolate, "debugPort"),
2640                        DebugPortGetter,
2641                        DebugPortSetter);
2642
2643   // define various internal methods
2644   NODE_SET_METHOD(process,
2645                   "_startProfilerIdleNotifier",
2646                   StartProfilerIdleNotifier);
2647   NODE_SET_METHOD(process,
2648                   "_stopProfilerIdleNotifier",
2649                   StopProfilerIdleNotifier);
2650   NODE_SET_METHOD(process, "_getActiveRequests", GetActiveRequests);
2651   NODE_SET_METHOD(process, "_getActiveHandles", GetActiveHandles);
2652   NODE_SET_METHOD(process, "reallyExit", Exit);
2653   NODE_SET_METHOD(process, "abort", Abort);
2654   NODE_SET_METHOD(process, "chdir", Chdir);
2655   NODE_SET_METHOD(process, "cwd", Cwd);
2656
2657   NODE_SET_METHOD(process, "umask", Umask);
2658
2659 #if defined(__POSIX__) && !defined(__ANDROID__)
2660   NODE_SET_METHOD(process, "getuid", GetUid);
2661   NODE_SET_METHOD(process, "setuid", SetUid);
2662
2663   NODE_SET_METHOD(process, "setgid", SetGid);
2664   NODE_SET_METHOD(process, "getgid", GetGid);
2665
2666   NODE_SET_METHOD(process, "getgroups", GetGroups);
2667   NODE_SET_METHOD(process, "setgroups", SetGroups);
2668   NODE_SET_METHOD(process, "initgroups", InitGroups);
2669 #endif  // __POSIX__ && !defined(__ANDROID__)
2670
2671   NODE_SET_METHOD(process, "_kill", Kill);
2672
2673   NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
2674   NODE_SET_METHOD(process, "_debugPause", DebugPause);
2675   NODE_SET_METHOD(process, "_debugEnd", DebugEnd);
2676
2677   NODE_SET_METHOD(process, "hrtime", Hrtime);
2678
2679   NODE_SET_METHOD(process, "dlopen", DLOpen);
2680
2681   NODE_SET_METHOD(process, "uptime", Uptime);
2682   NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2683
2684   NODE_SET_METHOD(process, "binding", Binding);
2685
2686   NODE_SET_METHOD(process, "_setupAsyncListener", SetupAsyncListener);
2687   NODE_SET_METHOD(process, "_setupNextTick", SetupNextTick);
2688   NODE_SET_METHOD(process, "_setupDomainUse", SetupDomainUse);
2689
2690   // values use to cross communicate with processNextTick
2691   Local<Object> tick_info_obj = Object::New();
2692   tick_info_obj->SetIndexedPropertiesToExternalArrayData(
2693       env->tick_info()->fields(),
2694       kExternalUnsignedIntArray,
2695       env->tick_info()->fields_count());
2696   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickInfo"), tick_info_obj);
2697
2698   // pre-set _events object for faster emit checks
2699   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_events"), Object::New());
2700 }
2701
2702
2703 #undef READONLY_PROPERTY
2704
2705
2706 static void AtExit() {
2707   uv_tty_reset_mode();
2708 }
2709
2710
2711 static void SignalExit(int signal) {
2712   uv_tty_reset_mode();
2713   _exit(128 + signal);
2714 }
2715
2716
2717 // Most of the time, it's best to use `console.error` to write
2718 // to the process.stderr stream.  However, in some cases, such as
2719 // when debugging the stream.Writable class or the process.nextTick
2720 // function, it is useful to bypass JavaScript entirely.
2721 static void RawDebug(const FunctionCallbackInfo<Value>& args) {
2722   HandleScope scope(node_isolate);
2723
2724   assert(args.Length() == 1 && args[0]->IsString() &&
2725          "must be called with a single string");
2726
2727   String::Utf8Value message(args[0]);
2728   fprintf(stderr, "%s\n", *message);
2729   fflush(stderr);
2730 }
2731
2732
2733 void Load(Environment* env) {
2734   HandleScope handle_scope(node_isolate);
2735
2736   // Compile, execute the src/node.js file. (Which was included as static C
2737   // string in node_natives.h. 'natve_node' is the string containing that
2738   // source code.)
2739
2740   // The node.js file returns a function 'f'
2741   atexit(AtExit);
2742
2743   TryCatch try_catch;
2744
2745   // Disable verbose mode to stop FatalException() handler from trying
2746   // to handle the exception. Errors this early in the start-up phase
2747   // are not safe to ignore.
2748   try_catch.SetVerbose(false);
2749
2750   Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js");
2751   Local<Value> f_value = ExecuteString(env, MainSource(), script_name);
2752   if (try_catch.HasCaught())  {
2753     ReportException(env, try_catch);
2754     exit(10);
2755   }
2756   assert(f_value->IsFunction());
2757   Local<Function> f = Local<Function>::Cast(f_value);
2758
2759   // Now we call 'f' with the 'process' variable that we've built up with
2760   // all our bindings. Inside node.js we'll take care of assigning things to
2761   // their places.
2762
2763   // We start the process this way in order to be more modular. Developers
2764   // who do not like how 'src/node.js' setups the module system but do like
2765   // Node's I/O bindings may want to replace 'f' with their own function.
2766
2767   // Add a reference to the global object
2768   Local<Object> global = env->context()->Global();
2769
2770 #if defined HAVE_DTRACE || defined HAVE_ETW
2771   InitDTrace(global);
2772 #endif
2773
2774 #if defined HAVE_PERFCTR
2775   InitPerfCounters(global);
2776 #endif
2777
2778   // Enable handling of uncaught exceptions
2779   // (FatalException(), break on uncaught exception in debugger)
2780   //
2781   // This is not strictly necessary since it's almost impossible
2782   // to attach the debugger fast enought to break on exception
2783   // thrown during process startup.
2784   try_catch.SetVerbose(true);
2785
2786   NODE_SET_METHOD(env->process_object(), "_rawDebug", RawDebug);
2787
2788   Local<Value> arg = env->process_object();
2789   f->Call(global, 1, &arg);
2790 }
2791
2792 static void PrintHelp();
2793
2794 static bool ParseDebugOpt(const char* arg) {
2795   const char* port = NULL;
2796
2797   if (!strcmp(arg, "--debug")) {
2798     use_debug_agent = true;
2799   } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
2800     use_debug_agent = true;
2801     port = arg + sizeof("--debug=") - 1;
2802   } else if (!strcmp(arg, "--debug-brk")) {
2803     use_debug_agent = true;
2804     debug_wait_connect = true;
2805   } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
2806     use_debug_agent = true;
2807     debug_wait_connect = true;
2808     port = arg + sizeof("--debug-brk=") - 1;
2809   } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
2810     port = arg + sizeof("--debug-port=") - 1;
2811   } else {
2812     return false;
2813   }
2814
2815   if (port != NULL) {
2816     debug_port = atoi(port);
2817     if (debug_port < 1024 || debug_port > 65535) {
2818       fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
2819       PrintHelp();
2820       exit(12);
2821     }
2822   }
2823
2824   return true;
2825 }
2826
2827 static void PrintHelp() {
2828   printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
2829          "       node debug script.js [arguments] \n"
2830          "\n"
2831          "Options:\n"
2832          "  -v, --version        print node's version\n"
2833          "  -e, --eval script    evaluate script\n"
2834          "  -p, --print          evaluate script and print result\n"
2835          "  -i, --interactive    always enter the REPL even if stdin\n"
2836          "                       does not appear to be a terminal\n"
2837          "  --no-deprecation     silence deprecation warnings\n"
2838          "  --trace-deprecation  show stack traces on deprecations\n"
2839          "  --v8-options         print v8 command line options\n"
2840          "  --max-stack-size=val set max v8 stack size (bytes)\n"
2841          "\n"
2842          "Environment variables:\n"
2843 #ifdef _WIN32
2844          "NODE_PATH              ';'-separated list of directories\n"
2845 #else
2846          "NODE_PATH              ':'-separated list of directories\n"
2847 #endif
2848          "                       prefixed to the module search path.\n"
2849          "NODE_MODULE_CONTEXTS   Set to 1 to load modules in their own\n"
2850          "                       global contexts.\n"
2851          "NODE_DISABLE_COLORS    Set to 1 to disable colors in the REPL\n"
2852          "\n"
2853          "Documentation can be found at http://nodejs.org/\n");
2854 }
2855
2856
2857 // Parse command line arguments.
2858 //
2859 // argv is modified in place. exec_argv and v8_argv are out arguments that
2860 // ParseArgs() allocates memory for and stores a pointer to the output
2861 // vector in.  The caller should free them with delete[].
2862 //
2863 // On exit:
2864 //
2865 //  * argv contains the arguments with node and V8 options filtered out.
2866 //  * exec_argv contains both node and V8 options and nothing else.
2867 //  * v8_argv contains argv[0] plus any V8 options
2868 static void ParseArgs(int* argc,
2869                       const char** argv,
2870                       int* exec_argc,
2871                       const char*** exec_argv,
2872                       int* v8_argc,
2873                       const char*** v8_argv) {
2874   const unsigned int nargs = static_cast<unsigned int>(*argc);
2875   const char** new_exec_argv = new const char*[nargs];
2876   const char** new_v8_argv = new const char*[nargs];
2877   const char** new_argv = new const char*[nargs];
2878
2879   for (unsigned int i = 0; i < nargs; ++i) {
2880     new_exec_argv[i] = NULL;
2881     new_v8_argv[i] = NULL;
2882     new_argv[i] = NULL;
2883   }
2884
2885   // exec_argv starts with the first option, the other two start with argv[0].
2886   unsigned int new_exec_argc = 0;
2887   unsigned int new_v8_argc = 1;
2888   unsigned int new_argc = 1;
2889   new_v8_argv[0] = argv[0];
2890   new_argv[0] = argv[0];
2891
2892   unsigned int index = 1;
2893   while (index < nargs && argv[index][0] == '-') {
2894     const char* const arg = argv[index];
2895     unsigned int args_consumed = 1;
2896
2897     if (ParseDebugOpt(arg)) {
2898       // Done, consumed by ParseDebugOpt().
2899     } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2900       printf("%s\n", NODE_VERSION);
2901       exit(0);
2902     } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2903       PrintHelp();
2904       exit(0);
2905     } else if (strcmp(arg, "--eval") == 0 ||
2906                strcmp(arg, "-e") == 0 ||
2907                strcmp(arg, "--print") == 0 ||
2908                strcmp(arg, "-pe") == 0 ||
2909                strcmp(arg, "-p") == 0) {
2910       bool is_eval = strchr(arg, 'e') != NULL;
2911       bool is_print = strchr(arg, 'p') != NULL;
2912       print_eval = print_eval || is_print;
2913       // --eval, -e and -pe always require an argument.
2914       if (is_eval == true) {
2915         args_consumed += 1;
2916         eval_string = argv[index + 1];
2917         if (eval_string == NULL) {
2918           fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
2919           exit(9);
2920         }
2921       } else if ((index + 1 < nargs) &&
2922                  argv[index + 1] != NULL &&
2923                  argv[index + 1][0] != '-') {
2924         args_consumed += 1;
2925         eval_string = argv[index + 1];
2926         if (strncmp(eval_string, "\\-", 2) == 0) {
2927           // Starts with "\\-": escaped expression, drop the backslash.
2928           eval_string += 1;
2929         }
2930       }
2931     } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
2932       force_repl = true;
2933     } else if (strcmp(arg, "--no-deprecation") == 0) {
2934       no_deprecation = true;
2935     } else if (strcmp(arg, "--trace-deprecation") == 0) {
2936       trace_deprecation = true;
2937     } else if (strcmp(arg, "--throw-deprecation") == 0) {
2938       throw_deprecation = true;
2939     } else if (strcmp(arg, "--v8-options") == 0) {
2940       new_v8_argv[new_v8_argc] = "--help";
2941       new_v8_argc += 1;
2942     } else {
2943       // V8 option.  Pass through as-is.
2944       new_v8_argv[new_v8_argc] = arg;
2945       new_v8_argc += 1;
2946     }
2947
2948     memcpy(new_exec_argv + new_exec_argc,
2949            argv + index,
2950            args_consumed * sizeof(*argv));
2951
2952     new_exec_argc += args_consumed;
2953     index += args_consumed;
2954   }
2955
2956   // Copy remaining arguments.
2957   const unsigned int args_left = nargs - index;
2958   memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
2959   new_argc += args_left;
2960
2961   *exec_argc = new_exec_argc;
2962   *exec_argv = new_exec_argv;
2963   *v8_argc = new_v8_argc;
2964   *v8_argv = new_v8_argv;
2965
2966   // Copy new_argv over argv and update argc.
2967   memcpy(argv, new_argv, new_argc * sizeof(*argv));
2968   delete[] new_argv;
2969   *argc = static_cast<int>(new_argc);
2970 }
2971
2972
2973 // Called from V8 Debug Agent TCP thread.
2974 static void DispatchMessagesDebugAgentCallback() {
2975   uv_async_send(&dispatch_debug_messages_async);
2976 }
2977
2978
2979 // Called from the main thread.
2980 static void EnableDebug(bool wait_connect) {
2981   assert(debugger_running == false);
2982   Isolate* isolate = node_isolate;  // TODO(bnoordhuis) Multi-isolate support.
2983   Isolate::Scope isolate_scope(isolate);
2984   HandleScope handle_scope(isolate);
2985   v8::Debug::SetDebugMessageDispatchHandler(DispatchMessagesDebugAgentCallback,
2986                                             false);
2987   debugger_running = v8::Debug::EnableAgent("node " NODE_VERSION,
2988                                             debug_port,
2989                                             wait_connect);
2990   if (debugger_running == false) {
2991     fprintf(stderr, "Starting debugger on port %d failed\n", debug_port);
2992     fflush(stderr);
2993     return;
2994   }
2995   fprintf(stderr, "Debugger listening on port %d\n", debug_port);
2996   fflush(stderr);
2997
2998   Environment* env = Environment::GetCurrentChecked(isolate);
2999   if (env == NULL)
3000     return;  // Still starting up.
3001
3002   Context::Scope context_scope(env->context());
3003   Local<Object> message = Object::New();
3004   message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
3005                FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
3006   Local<Value> argv[] = {
3007     FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
3008     message
3009   };
3010   MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv);
3011 }
3012
3013
3014 // Called from the main thread.
3015 static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle, int status) {
3016   if (debugger_running == false) {
3017     fprintf(stderr, "Starting debugger agent.\n");
3018     EnableDebug(false);
3019   }
3020   Isolate::Scope isolate_scope(node_isolate);
3021   v8::Debug::ProcessDebugMessages();
3022 }
3023
3024
3025 #ifdef __POSIX__
3026 static volatile sig_atomic_t caught_early_debug_signal;
3027
3028
3029 static void EarlyDebugSignalHandler(int signo) {
3030   caught_early_debug_signal = 1;
3031 }
3032
3033
3034 static void InstallEarlyDebugSignalHandler() {
3035   struct sigaction sa;
3036   memset(&sa, 0, sizeof(sa));
3037   sa.sa_handler = EarlyDebugSignalHandler;
3038   sigaction(SIGUSR1, &sa, NULL);
3039 }
3040
3041
3042 static void EnableDebugSignalHandler(int signo) {
3043   // Call only async signal-safe functions here!
3044   v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3045   uv_async_send(&dispatch_debug_messages_async);
3046 }
3047
3048
3049 static void RegisterSignalHandler(int signal, void (*handler)(int signal)) {
3050   struct sigaction sa;
3051   memset(&sa, 0, sizeof(sa));
3052   sa.sa_handler = handler;
3053   sigfillset(&sa.sa_mask);
3054   sigaction(signal, &sa, NULL);
3055 }
3056
3057
3058 void DebugProcess(const FunctionCallbackInfo<Value>& args) {
3059   HandleScope scope(node_isolate);
3060
3061   if (args.Length() != 1) {
3062     return ThrowError("Invalid number of arguments.");
3063   }
3064
3065   pid_t pid;
3066   int r;
3067
3068   pid = args[0]->IntegerValue();
3069   r = kill(pid, SIGUSR1);
3070   if (r != 0) {
3071     return ThrowErrnoException(errno, "kill");
3072   }
3073 }
3074
3075
3076 static int RegisterDebugSignalHandler() {
3077   // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3078   RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
3079   // If we caught a SIGUSR1 during the bootstrap process, re-raise it
3080   // now that the debugger infrastructure is in place.
3081   if (caught_early_debug_signal)
3082     raise(SIGUSR1);
3083   return 0;
3084 }
3085 #endif  // __POSIX__
3086
3087
3088 #ifdef _WIN32
3089 DWORD WINAPI EnableDebugThreadProc(void* arg) {
3090   v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3091   uv_async_send(&dispatch_debug_messages_async);
3092   return 0;
3093 }
3094
3095
3096 static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
3097     size_t buf_len) {
3098   return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
3099 }
3100
3101
3102 static int RegisterDebugSignalHandler() {
3103   wchar_t mapping_name[32];
3104   HANDLE mapping_handle;
3105   DWORD pid;
3106   LPTHREAD_START_ROUTINE* handler;
3107
3108   pid = GetCurrentProcessId();
3109
3110   if (GetDebugSignalHandlerMappingName(pid,
3111                                        mapping_name,
3112                                        ARRAY_SIZE(mapping_name)) < 0) {
3113     return -1;
3114   }
3115
3116   mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
3117                                       NULL,
3118                                       PAGE_READWRITE,
3119                                       0,
3120                                       sizeof *handler,
3121                                       mapping_name);
3122   if (mapping_handle == NULL) {
3123     return -1;
3124   }
3125
3126   handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3127       MapViewOfFile(mapping_handle,
3128                     FILE_MAP_ALL_ACCESS,
3129                     0,
3130                     0,
3131                     sizeof *handler));
3132   if (handler == NULL) {
3133     CloseHandle(mapping_handle);
3134     return -1;
3135   }
3136
3137   *handler = EnableDebugThreadProc;
3138
3139   UnmapViewOfFile(static_cast<void*>(handler));
3140
3141   return 0;
3142 }
3143
3144
3145 static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
3146   HandleScope scope(node_isolate);
3147   DWORD pid;
3148   HANDLE process = NULL;
3149   HANDLE thread = NULL;
3150   HANDLE mapping = NULL;
3151   wchar_t mapping_name[32];
3152   LPTHREAD_START_ROUTINE* handler = NULL;
3153
3154   if (args.Length() != 1) {
3155     ThrowError("Invalid number of arguments.");
3156     goto out;
3157   }
3158
3159   pid = (DWORD) args[0]->IntegerValue();
3160
3161   process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
3162                             PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
3163                             PROCESS_VM_READ,
3164                         FALSE,
3165                         pid);
3166   if (process == NULL) {
3167     ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
3168     goto out;
3169   }
3170
3171   if (GetDebugSignalHandlerMappingName(pid,
3172                                        mapping_name,
3173                                        ARRAY_SIZE(mapping_name)) < 0) {
3174     ThrowErrnoException(errno, "sprintf");
3175     goto out;
3176   }
3177
3178   mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
3179   if (mapping == NULL) {
3180     ThrowException(WinapiErrnoException(GetLastError(), "OpenFileMappingW"));
3181     goto out;
3182   }
3183
3184   handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3185       MapViewOfFile(mapping,
3186                     FILE_MAP_READ,
3187                     0,
3188                     0,
3189                     sizeof *handler));
3190   if (handler == NULL || *handler == NULL) {
3191     ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
3192     goto out;
3193   }
3194
3195   thread = CreateRemoteThread(process,
3196                               NULL,
3197                               0,
3198                               *handler,
3199                               NULL,
3200                               0,
3201                               NULL);
3202   if (thread == NULL) {
3203     ThrowException(WinapiErrnoException(GetLastError(), "CreateRemoteThread"));
3204     goto out;
3205   }
3206
3207   // Wait for the thread to terminate
3208   if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
3209     ThrowException(WinapiErrnoException(GetLastError(), "WaitForSingleObject"));
3210     goto out;
3211   }
3212
3213  out:
3214   if (process != NULL)
3215     CloseHandle(process);
3216   if (thread != NULL)
3217     CloseHandle(thread);
3218   if (handler != NULL)
3219     UnmapViewOfFile(handler);
3220   if (mapping != NULL)
3221     CloseHandle(mapping);
3222 }
3223 #endif  // _WIN32
3224
3225
3226 static void DebugPause(const FunctionCallbackInfo<Value>& args) {
3227   v8::Debug::DebugBreak(node_isolate);
3228 }
3229
3230
3231 static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
3232   if (debugger_running) {
3233     v8::Debug::DisableAgent();
3234     debugger_running = false;
3235   }
3236 }
3237
3238
3239 void Init(int* argc,
3240           const char** argv,
3241           int* exec_argc,
3242           const char*** exec_argv) {
3243   // Initialize prog_start_time to get relative uptime.
3244   uv_uptime(&prog_start_time);
3245
3246   // Make inherited handles noninheritable.
3247   uv_disable_stdio_inheritance();
3248
3249   // init async debug messages dispatching
3250   // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3251   uv_async_init(uv_default_loop(),
3252                 &dispatch_debug_messages_async,
3253                 DispatchDebugMessagesAsyncCallback);
3254   uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
3255
3256   // Parse a few arguments which are specific to Node.
3257   int v8_argc;
3258   const char** v8_argv;
3259   ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
3260
3261   // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
3262   // manually?  That would give us a little more control over its runtime
3263   // behavior but it could also interfere with the user's intentions in ways
3264   // we fail to anticipate.  Dillema.
3265   for (int i = 1; i < v8_argc; ++i) {
3266     if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
3267       v8_is_profiling = true;
3268       break;
3269     }
3270   }
3271
3272   // The const_cast doesn't violate conceptual const-ness.  V8 doesn't modify
3273   // the argv array or the elements it points to.
3274   V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
3275
3276   // Anything that's still in v8_argv is not a V8 or a node option.
3277   for (int i = 1; i < v8_argc; i++) {
3278     fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
3279   }
3280   delete[] v8_argv;
3281   v8_argv = NULL;
3282
3283   if (v8_argc > 1) {
3284     exit(9);
3285   }
3286
3287   if (debug_wait_connect) {
3288     const char expose_debug_as[] = "--expose_debug_as=v8debug";
3289     V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
3290   }
3291
3292   V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton);
3293
3294   // Fetch a reference to the main isolate, so we have a reference to it
3295   // even when we need it to access it from another (debugger) thread.
3296   node_isolate = Isolate::GetCurrent();
3297
3298 #ifdef __POSIX__
3299   // Raise the open file descriptor limit.
3300   {  // NOLINT (whitespace/braces)
3301     struct rlimit lim;
3302     if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
3303       // Do a binary search for the limit.
3304       rlim_t min = lim.rlim_cur;
3305       rlim_t max = 1 << 20;
3306       // But if there's a defined upper bound, don't search, just set it.
3307       if (lim.rlim_max != RLIM_INFINITY) {
3308         min = lim.rlim_max;
3309         max = lim.rlim_max;
3310       }
3311       do {
3312         lim.rlim_cur = min + (max - min) / 2;
3313         if (setrlimit(RLIMIT_NOFILE, &lim)) {
3314           max = lim.rlim_cur;
3315         } else {
3316           min = lim.rlim_cur;
3317         }
3318       } while (min + 1 < max);
3319     }
3320   }
3321   // Ignore SIGPIPE
3322   RegisterSignalHandler(SIGPIPE, SIG_IGN);
3323   RegisterSignalHandler(SIGINT, SignalExit);
3324   RegisterSignalHandler(SIGTERM, SignalExit);
3325 #endif  // __POSIX__
3326
3327   V8::SetFatalErrorHandler(node::OnFatalError);
3328   V8::AddMessageListener(OnMessage);
3329
3330   // If the --debug flag was specified then initialize the debug thread.
3331   if (use_debug_agent) {
3332     EnableDebug(debug_wait_connect);
3333   } else {
3334     RegisterDebugSignalHandler();
3335   }
3336 }
3337
3338
3339 struct AtExitCallback {
3340   AtExitCallback* next_;
3341   void (*cb_)(void* arg);
3342   void* arg_;
3343 };
3344
3345 static AtExitCallback* at_exit_functions_;
3346
3347
3348 // TODO(bnoordhuis) Turn into per-context event.
3349 void RunAtExit(Environment* env) {
3350   AtExitCallback* p = at_exit_functions_;
3351   at_exit_functions_ = NULL;
3352
3353   while (p) {
3354     AtExitCallback* q = p->next_;
3355     p->cb_(p->arg_);
3356     delete p;
3357     p = q;
3358   }
3359 }
3360
3361
3362 void AtExit(void (*cb)(void* arg), void* arg) {
3363   AtExitCallback* p = new AtExitCallback;
3364   p->cb_ = cb;
3365   p->arg_ = arg;
3366   p->next_ = at_exit_functions_;
3367   at_exit_functions_ = p;
3368 }
3369
3370
3371 int EmitExit(Environment* env) {
3372   // process.emit('exit')
3373   HandleScope handle_scope(env->isolate());
3374   Context::Scope context_scope(env->context());
3375   Local<Object> process_object = env->process_object();
3376   process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_exiting"),
3377                       True(node_isolate));
3378
3379   Handle<String> exitCode = FIXED_ONE_BYTE_STRING(node_isolate, "exitCode");
3380   int code = process_object->Get(exitCode)->IntegerValue();
3381
3382   Local<Value> args[] = {
3383     FIXED_ONE_BYTE_STRING(node_isolate, "exit"),
3384     Integer::New(code, node_isolate)
3385   };
3386
3387   MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3388
3389   // Reload exit code, it may be changed by `emit('exit')`
3390   return process_object->Get(exitCode)->IntegerValue();
3391 }
3392
3393
3394 Environment* CreateEnvironment(Isolate* isolate,
3395                                int argc,
3396                                const char* const* argv,
3397                                int exec_argc,
3398                                const char* const* exec_argv) {
3399   HandleScope handle_scope(isolate);
3400
3401   Local<Context> context = Context::New(isolate);
3402   Context::Scope context_scope(context);
3403   Environment* env = Environment::New(context);
3404
3405   uv_check_init(env->event_loop(), env->immediate_check_handle());
3406   uv_unref(
3407       reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
3408   uv_idle_init(env->event_loop(), env->immediate_idle_handle());
3409
3410   // Inform V8's CPU profiler when we're idle.  The profiler is sampling-based
3411   // but not all samples are created equal; mark the wall clock time spent in
3412   // epoll_wait() and friends so profiling tools can filter it out.  The samples
3413   // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
3414   // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
3415   // probably fortify in the API contract, namely that the last started prepare
3416   // or check watcher runs first.  It's not 100% foolproof; if an add-on starts
3417   // a prepare or check watcher after us, any samples attributed to its callback
3418   // will be recorded with state=IDLE.
3419   uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
3420   uv_check_init(env->event_loop(), env->idle_check_handle());
3421   uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
3422   uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
3423
3424   if (v8_is_profiling) {
3425     StartProfilerIdleNotifier(env);
3426   }
3427
3428   Local<FunctionTemplate> process_template = FunctionTemplate::New();
3429   process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
3430
3431   Local<Object> process_object = process_template->GetFunction()->NewInstance();
3432   env->set_process_object(process_object);
3433
3434   SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
3435   Load(env);
3436
3437   return env;
3438 }
3439
3440
3441 int Start(int argc, char** argv) {
3442 #if !defined(_WIN32)
3443   // Try hard not to lose SIGUSR1 signals during the bootstrap process.
3444   InstallEarlyDebugSignalHandler();
3445 #endif
3446
3447   assert(argc > 0);
3448
3449   // Hack around with the argv pointer. Used for process.title = "blah".
3450   argv = uv_setup_args(argc, argv);
3451
3452   // This needs to run *before* V8::Initialize().  The const_cast is not
3453   // optional, in case you're wondering.
3454   int exec_argc;
3455   const char** exec_argv;
3456   Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
3457
3458 #if HAVE_OPENSSL
3459   // V8 on Windows doesn't have a good source of entropy. Seed it from
3460   // OpenSSL's pool.
3461   V8::SetEntropySource(crypto::EntropySource);
3462 #endif
3463
3464   int code;
3465   V8::Initialize();
3466   {
3467     Locker locker(node_isolate);
3468     Environment* env =
3469         CreateEnvironment(node_isolate, argc, argv, exec_argc, exec_argv);
3470     // This Context::Scope is here so EnableDebug() can look up the current
3471     // environment with Environment::GetCurrentChecked().
3472     // TODO(bnoordhuis) Reorder the debugger initialization logic so it can
3473     // be removed.
3474     Context::Scope context_scope(env->context());
3475     uv_run(env->event_loop(), UV_RUN_DEFAULT);
3476     code = EmitExit(env);
3477     RunAtExit(env);
3478     env->Dispose();
3479     env = NULL;
3480   }
3481
3482 #ifndef NDEBUG
3483   // Clean up. Not strictly necessary.
3484   V8::Dispose();
3485 #endif  // NDEBUG
3486
3487   delete[] exec_argv;
3488   exec_argv = NULL;
3489
3490   return code;
3491 }
3492
3493
3494 }  // namespace node