Change string.h to strings.h compile on solaris
[platform/upstream/nodejs.git] / src / node.cc
1 // Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
2 #include <node.h>
3
4 #include <locale.h>
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <strings.h>
9 #include <limits.h> /* PATH_MAX */
10 #include <assert.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <dlfcn.h> /* dlopen(), dlsym() */
14 #include <sys/types.h>
15 #include <unistd.h> /* setuid, getuid */
16
17 #include <node_buffer.h>
18 #include <node_io_watcher.h>
19 #include <node_net2.h>
20 #include <node_events.h>
21 #include <node_cares.h>
22 #include <node_file.h>
23 #if 0
24 // not in use
25 # include <node_idle_watcher.h>
26 #endif
27 #include <node_http_parser.h>
28 #include <node_signal_watcher.h>
29 #include <node_stat_watcher.h>
30 #include <node_timer.h>
31 #include <node_child_process.h>
32 #include <node_constants.h>
33 #include <node_stdio.h>
34 #include <node_natives.h>
35 #include <node_version.h>
36 #ifdef HAVE_OPENSSL
37 #include <node_crypto.h>
38 #endif
39 #include <node_script.h>
40
41 #include <v8-debug.h>
42
43 using namespace v8;
44
45 extern char **environ;
46
47 namespace node {
48
49 static Persistent<Object> process;
50
51 static Persistent<String> errno_symbol;
52 static Persistent<String> syscall_symbol;
53
54 static Persistent<String> dev_symbol;
55 static Persistent<String> ino_symbol;
56 static Persistent<String> mode_symbol;
57 static Persistent<String> nlink_symbol;
58 static Persistent<String> uid_symbol;
59 static Persistent<String> gid_symbol;
60 static Persistent<String> rdev_symbol;
61 static Persistent<String> size_symbol;
62 static Persistent<String> blksize_symbol;
63 static Persistent<String> blocks_symbol;
64 static Persistent<String> atime_symbol;
65 static Persistent<String> mtime_symbol;
66 static Persistent<String> ctime_symbol;
67
68 static Persistent<String> rss_symbol;
69 static Persistent<String> vsize_symbol;
70 static Persistent<String> heap_total_symbol;
71 static Persistent<String> heap_used_symbol;
72
73 static Persistent<String> listeners_symbol;
74 static Persistent<String> uncaught_exception_symbol;
75 static Persistent<String> emit_symbol;
76
77 static int option_end_index = 0;
78 static bool use_debug_agent = false;
79 static bool debug_wait_connect = false;
80 static int debug_port=5858;
81
82 static ev_prepare next_tick_watcher;
83 static ev_idle tick_spinner;
84 static bool need_tick_cb;
85 static Persistent<String> tick_callback_sym;
86
87 static ev_async eio_want_poll_notifier;
88 static ev_async eio_done_poll_notifier;
89 static ev_idle  eio_poller;
90
91 // We need to notify V8 when we're idle so that it can run the garbage
92 // collector. The interface to this is V8::IdleNotification(). It returns
93 // true if the heap hasn't be fully compacted, and needs to be run again.
94 // Returning false means that it doesn't have anymore work to do.
95 //
96 // A rather convoluted algorithm has been devised to determine when Node is
97 // idle. You'll have to figure it out for yourself.
98 static ev_check gc_check;
99 static ev_idle  gc_idle;
100 static ev_timer gc_timer;
101 bool need_gc;
102
103
104 #define FAST_TICK 0.7
105 #define GC_WAIT_TIME 5.
106 #define RPM_SAMPLES 100
107 #define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
108 static ev_tstamp tick_times[RPM_SAMPLES];
109 static int tick_time_head;
110
111 static void StartGCTimer () {
112   if (!ev_is_active(&gc_timer)) {
113     ev_timer_start(EV_DEFAULT_UC_ &gc_timer);
114     ev_unref(EV_DEFAULT_UC);
115   }
116 }
117
118 static void StopGCTimer () {
119   if (ev_is_active(&gc_timer)) {
120     ev_ref(EV_DEFAULT_UC);
121     ev_timer_stop(&gc_timer);
122   }
123 }
124
125 static void Idle(EV_P_ ev_idle *watcher, int revents) {
126   assert(watcher == &gc_idle);
127   assert(revents == EV_IDLE);
128
129   //fprintf(stderr, "idle\n");
130
131   if (V8::IdleNotification()) {
132     ev_idle_stop(EV_A_ watcher);
133     StopGCTimer();
134   }
135 }
136
137
138 // Called directly after every call to select() (or epoll, or whatever)
139 static void Check(EV_P_ ev_check *watcher, int revents) {
140   assert(watcher == &gc_check);
141   assert(revents == EV_CHECK);
142
143   tick_times[tick_time_head] = ev_now();
144   tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
145
146   StartGCTimer();
147
148   for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
149     double d = TICK_TIME(i+1) - TICK_TIME(i+2);
150     //printf("d = %f\n", d);
151     // If in the last 5 ticks the difference between
152     // ticks was less than 0.7 seconds, then continue.
153     if (d < FAST_TICK) {
154       //printf("---\n");
155       return;
156     }
157   }
158
159   // Otherwise start the gc!
160
161   //fprintf(stderr, "start idle 2\n");
162   ev_idle_start(EV_A_ &gc_idle);
163 }
164
165
166 static Handle<Value> NeedTickCallback(const Arguments& args) {
167   HandleScope scope;
168   need_tick_cb = true;
169   ev_idle_start(EV_DEFAULT_UC_ &tick_spinner);
170   return Undefined();
171 }
172
173
174 static void Spin(EV_P_ ev_idle *watcher, int revents) {
175   assert(watcher == &tick_spinner);
176   assert(revents == EV_IDLE);
177 }
178
179
180 static void Tick(EV_P_ ev_prepare *watcher, int revents) {
181   assert(watcher == &next_tick_watcher);
182   assert(revents == EV_PREPARE);
183
184   // Avoid entering a V8 scope.
185   if (!need_tick_cb) return;
186
187   need_tick_cb = false;
188   ev_idle_stop(EV_DEFAULT_UC_ &tick_spinner);
189
190   HandleScope scope;
191
192   if (tick_callback_sym.IsEmpty()) {
193     // Lazily set the symbol
194     tick_callback_sym =
195       Persistent<String>::New(String::NewSymbol("_tickCallback"));
196   }
197
198   Local<Value> cb_v = process->Get(tick_callback_sym);
199   if (!cb_v->IsFunction()) return;
200   Local<Function> cb = Local<Function>::Cast(cb_v);
201
202   TryCatch try_catch;
203
204   cb->Call(process, 0, NULL);
205
206   if (try_catch.HasCaught()) {
207     FatalException(try_catch);
208   }
209 }
210
211
212 static void DoPoll(EV_P_ ev_idle *watcher, int revents) {
213   assert(watcher == &eio_poller);
214   assert(revents == EV_IDLE);
215
216   //printf("eio_poller\n");
217
218   if (eio_poll() != -1) {
219     //printf("eio_poller stop\n");
220     ev_idle_stop(EV_DEFAULT_UC_ watcher);
221   }
222 }
223
224
225 // Called from the main thread.
226 static void WantPollNotifier(EV_P_ ev_async *watcher, int revents) {
227   assert(watcher == &eio_want_poll_notifier);
228   assert(revents == EV_ASYNC);
229
230   //printf("want poll notifier\n");
231
232   if (eio_poll() == -1) {
233     //printf("eio_poller start\n");
234     ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
235   }
236 }
237
238
239 static void DonePollNotifier(EV_P_ ev_async *watcher, int revents) {
240   assert(watcher == &eio_done_poll_notifier);
241   assert(revents == EV_ASYNC);
242
243   //printf("done poll notifier\n");
244
245   if (eio_poll() != -1) {
246     //printf("eio_poller stop\n");
247     ev_idle_stop(EV_DEFAULT_UC_ &eio_poller);
248   }
249 }
250
251
252 // EIOWantPoll() is called from the EIO thread pool each time an EIO
253 // request (that is, one of the node.fs.* functions) has completed.
254 static void EIOWantPoll(void) {
255   // Signal the main thread that eio_poll need to be processed.
256   ev_async_send(EV_DEFAULT_UC_ &eio_want_poll_notifier);
257 }
258
259
260 static void EIODonePoll(void) {
261   // Signal the main thread that we should stop calling eio_poll().
262   // from the idle watcher.
263   ev_async_send(EV_DEFAULT_UC_ &eio_done_poll_notifier);
264 }
265
266
267 static inline const char *errno_string(int errorno) {
268 #define ERRNO_CASE(e)  case e: return #e;
269   switch (errorno) {
270
271 #ifdef EACCES
272   ERRNO_CASE(EACCES);
273 #endif
274
275 #ifdef EADDRINUSE
276   ERRNO_CASE(EADDRINUSE);
277 #endif
278
279 #ifdef EADDRNOTAVAIL
280   ERRNO_CASE(EADDRNOTAVAIL);
281 #endif
282
283 #ifdef EAFNOSUPPORT
284   ERRNO_CASE(EAFNOSUPPORT);
285 #endif
286
287 #ifdef EAGAIN
288   ERRNO_CASE(EAGAIN);
289 #endif
290
291 #ifdef EWOULDBLOCK
292 # if EAGAIN != EWOULDBLOCK
293   ERRNO_CASE(EWOULDBLOCK);
294 # endif
295 #endif
296
297 #ifdef EALREADY
298   ERRNO_CASE(EALREADY);
299 #endif
300
301 #ifdef EBADF
302   ERRNO_CASE(EBADF);
303 #endif
304
305 #ifdef EBADMSG
306   ERRNO_CASE(EBADMSG);
307 #endif
308
309 #ifdef EBUSY
310   ERRNO_CASE(EBUSY);
311 #endif
312
313 #ifdef ECANCELED
314   ERRNO_CASE(ECANCELED);
315 #endif
316
317 #ifdef ECHILD
318   ERRNO_CASE(ECHILD);
319 #endif
320
321 #ifdef ECONNABORTED
322   ERRNO_CASE(ECONNABORTED);
323 #endif
324
325 #ifdef ECONNREFUSED
326   ERRNO_CASE(ECONNREFUSED);
327 #endif
328
329 #ifdef ECONNRESET
330   ERRNO_CASE(ECONNRESET);
331 #endif
332
333 #ifdef EDEADLK
334   ERRNO_CASE(EDEADLK);
335 #endif
336
337 #ifdef EDESTADDRREQ
338   ERRNO_CASE(EDESTADDRREQ);
339 #endif
340
341 #ifdef EDOM
342   ERRNO_CASE(EDOM);
343 #endif
344
345 #ifdef EDQUOT
346   ERRNO_CASE(EDQUOT);
347 #endif
348
349 #ifdef EEXIST
350   ERRNO_CASE(EEXIST);
351 #endif
352
353 #ifdef EFAULT
354   ERRNO_CASE(EFAULT);
355 #endif
356
357 #ifdef EFBIG
358   ERRNO_CASE(EFBIG);
359 #endif
360
361 #ifdef EHOSTUNREACH
362   ERRNO_CASE(EHOSTUNREACH);
363 #endif
364
365 #ifdef EIDRM
366   ERRNO_CASE(EIDRM);
367 #endif
368
369 #ifdef EILSEQ
370   ERRNO_CASE(EILSEQ);
371 #endif
372
373 #ifdef EINPROGRESS
374   ERRNO_CASE(EINPROGRESS);
375 #endif
376
377 #ifdef EINTR
378   ERRNO_CASE(EINTR);
379 #endif
380
381 #ifdef EINVAL
382   ERRNO_CASE(EINVAL);
383 #endif
384
385 #ifdef EIO
386   ERRNO_CASE(EIO);
387 #endif
388
389 #ifdef EISCONN
390   ERRNO_CASE(EISCONN);
391 #endif
392
393 #ifdef EISDIR
394   ERRNO_CASE(EISDIR);
395 #endif
396
397 #ifdef ELOOP
398   ERRNO_CASE(ELOOP);
399 #endif
400
401 #ifdef EMFILE
402   ERRNO_CASE(EMFILE);
403 #endif
404
405 #ifdef EMLINK
406   ERRNO_CASE(EMLINK);
407 #endif
408
409 #ifdef EMSGSIZE
410   ERRNO_CASE(EMSGSIZE);
411 #endif
412
413 #ifdef EMULTIHOP
414   ERRNO_CASE(EMULTIHOP);
415 #endif
416
417 #ifdef ENAMETOOLONG
418   ERRNO_CASE(ENAMETOOLONG);
419 #endif
420
421 #ifdef ENETDOWN
422   ERRNO_CASE(ENETDOWN);
423 #endif
424
425 #ifdef ENETRESET
426   ERRNO_CASE(ENETRESET);
427 #endif
428
429 #ifdef ENETUNREACH
430   ERRNO_CASE(ENETUNREACH);
431 #endif
432
433 #ifdef ENFILE
434   ERRNO_CASE(ENFILE);
435 #endif
436
437 #ifdef ENOBUFS
438   ERRNO_CASE(ENOBUFS);
439 #endif
440
441 #ifdef ENODATA
442   ERRNO_CASE(ENODATA);
443 #endif
444
445 #ifdef ENODEV
446   ERRNO_CASE(ENODEV);
447 #endif
448
449 #ifdef ENOENT
450   ERRNO_CASE(ENOENT);
451 #endif
452
453 #ifdef ENOEXEC
454   ERRNO_CASE(ENOEXEC);
455 #endif
456
457 #ifdef ENOLINK
458   ERRNO_CASE(ENOLINK);
459 #endif
460
461 #ifdef ENOLCK
462 # if ENOLINK != ENOLCK
463   ERRNO_CASE(ENOLCK);
464 # endif
465 #endif
466
467 #ifdef ENOMEM
468   ERRNO_CASE(ENOMEM);
469 #endif
470
471 #ifdef ENOMSG
472   ERRNO_CASE(ENOMSG);
473 #endif
474
475 #ifdef ENOPROTOOPT
476   ERRNO_CASE(ENOPROTOOPT);
477 #endif
478
479 #ifdef ENOSPC
480   ERRNO_CASE(ENOSPC);
481 #endif
482
483 #ifdef ENOSR
484   ERRNO_CASE(ENOSR);
485 #endif
486
487 #ifdef ENOSTR
488   ERRNO_CASE(ENOSTR);
489 #endif
490
491 #ifdef ENOSYS
492   ERRNO_CASE(ENOSYS);
493 #endif
494
495 #ifdef ENOTCONN
496   ERRNO_CASE(ENOTCONN);
497 #endif
498
499 #ifdef ENOTDIR
500   ERRNO_CASE(ENOTDIR);
501 #endif
502
503 #ifdef ENOTEMPTY
504   ERRNO_CASE(ENOTEMPTY);
505 #endif
506
507 #ifdef ENOTSOCK
508   ERRNO_CASE(ENOTSOCK);
509 #endif
510
511 #ifdef ENOTSUP
512   ERRNO_CASE(ENOTSUP);
513 #else
514 # ifdef EOPNOTSUPP
515   ERRNO_CASE(EOPNOTSUPP);
516 # endif
517 #endif
518
519 #ifdef ENOTTY
520   ERRNO_CASE(ENOTTY);
521 #endif
522
523 #ifdef ENXIO
524   ERRNO_CASE(ENXIO);
525 #endif
526
527
528 #ifdef EOVERFLOW
529   ERRNO_CASE(EOVERFLOW);
530 #endif
531
532 #ifdef EPERM
533   ERRNO_CASE(EPERM);
534 #endif
535
536 #ifdef EPIPE
537   ERRNO_CASE(EPIPE);
538 #endif
539
540 #ifdef EPROTO
541   ERRNO_CASE(EPROTO);
542 #endif
543
544 #ifdef EPROTONOSUPPORT
545   ERRNO_CASE(EPROTONOSUPPORT);
546 #endif
547
548 #ifdef EPROTOTYPE
549   ERRNO_CASE(EPROTOTYPE);
550 #endif
551
552 #ifdef ERANGE
553   ERRNO_CASE(ERANGE);
554 #endif
555
556 #ifdef EROFS
557   ERRNO_CASE(EROFS);
558 #endif
559
560 #ifdef ESPIPE
561   ERRNO_CASE(ESPIPE);
562 #endif
563
564 #ifdef ESRCH
565   ERRNO_CASE(ESRCH);
566 #endif
567
568 #ifdef ESTALE
569   ERRNO_CASE(ESTALE);
570 #endif
571
572 #ifdef ETIME
573   ERRNO_CASE(ETIME);
574 #endif
575
576 #ifdef ETIMEDOUT
577   ERRNO_CASE(ETIMEDOUT);
578 #endif
579
580 #ifdef ETXTBSY
581   ERRNO_CASE(ETXTBSY);
582 #endif
583
584 #ifdef EXDEV
585   ERRNO_CASE(EXDEV);
586 #endif
587
588   default: return "";
589   }
590 }
591
592 const char *signo_string(int signo) {
593 #define SIGNO_CASE(e)  case e: return #e;
594   switch (signo) {
595
596 #ifdef SIGHUP
597   SIGNO_CASE(SIGHUP);
598 #endif
599
600 #ifdef SIGINT
601   SIGNO_CASE(SIGINT);
602 #endif
603
604 #ifdef SIGQUIT
605   SIGNO_CASE(SIGQUIT);
606 #endif
607
608 #ifdef SIGILL
609   SIGNO_CASE(SIGILL);
610 #endif
611
612 #ifdef SIGTRAP
613   SIGNO_CASE(SIGTRAP);
614 #endif
615
616 #ifdef SIGABRT
617   SIGNO_CASE(SIGABRT);
618 #endif
619
620 #ifdef SIGIOT
621 # if SIGABRT != SIGIOT
622   SIGNO_CASE(SIGIOT);
623 # endif
624 #endif
625
626 #ifdef SIGBUS
627   SIGNO_CASE(SIGBUS);
628 #endif
629
630 #ifdef SIGFPE
631   SIGNO_CASE(SIGFPE);
632 #endif
633
634 #ifdef SIGKILL
635   SIGNO_CASE(SIGKILL);
636 #endif
637
638 #ifdef SIGUSR1
639   SIGNO_CASE(SIGUSR1);
640 #endif
641
642 #ifdef SIGSEGV
643   SIGNO_CASE(SIGSEGV);
644 #endif
645
646 #ifdef SIGUSR2
647   SIGNO_CASE(SIGUSR2);
648 #endif
649
650 #ifdef SIGPIPE
651   SIGNO_CASE(SIGPIPE);
652 #endif
653
654 #ifdef SIGALRM
655   SIGNO_CASE(SIGALRM);
656 #endif
657
658   SIGNO_CASE(SIGTERM);
659   SIGNO_CASE(SIGCHLD);
660
661 #ifdef SIGSTKFLT
662   SIGNO_CASE(SIGSTKFLT);
663 #endif
664
665
666 #ifdef SIGCONT
667   SIGNO_CASE(SIGCONT);
668 #endif
669
670 #ifdef SIGSTOP
671   SIGNO_CASE(SIGSTOP);
672 #endif
673
674 #ifdef SIGTSTP
675   SIGNO_CASE(SIGTSTP);
676 #endif
677
678 #ifdef SIGTTIN
679   SIGNO_CASE(SIGTTIN);
680 #endif
681
682 #ifdef SIGTTOU
683   SIGNO_CASE(SIGTTOU);
684 #endif
685
686 #ifdef SIGURG
687   SIGNO_CASE(SIGURG);
688 #endif
689
690 #ifdef SIGXCPU
691   SIGNO_CASE(SIGXCPU);
692 #endif
693
694 #ifdef SIGXFSZ
695   SIGNO_CASE(SIGXFSZ);
696 #endif
697
698 #ifdef SIGVTALRM
699   SIGNO_CASE(SIGVTALRM);
700 #endif
701
702 #ifdef SIGPROF
703   SIGNO_CASE(SIGPROF);
704 #endif
705
706 #ifdef SIGWINCH
707   SIGNO_CASE(SIGWINCH);
708 #endif
709
710 #ifdef SIGIO
711   SIGNO_CASE(SIGIO);
712 #endif
713
714 #ifdef SIGPOLL
715 # if SIGPOLL != SIGIO
716   SIGNO_CASE(SIGPOLL);
717 # endif
718 #endif
719
720 #ifdef SIGLOST
721   SIGNO_CASE(SIGLOST);
722 #endif
723
724 #ifdef SIGPWR
725   SIGNO_CASE(SIGPWR);
726 #endif
727
728 #ifdef SIGSYS
729   SIGNO_CASE(SIGSYS);
730 #endif
731
732   default: return "";
733   }
734 }
735
736
737 Local<Value> ErrnoException(int errorno,
738                             const char *syscall,
739                             const char *msg) {
740   Local<String> estring = String::NewSymbol(errno_string(errorno));
741   if (!msg[0]) msg = strerror(errorno);
742   Local<String> message = String::NewSymbol(msg);
743
744   Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
745   Local<String> cons2 = String::Concat(cons1, message);
746
747   Local<Value> e = Exception::Error(cons2);
748
749   Local<Object> obj = e->ToObject();
750
751   if (errno_symbol.IsEmpty()) {
752     syscall_symbol = NODE_PSYMBOL("syscall");
753     errno_symbol = NODE_PSYMBOL("errno");
754   }
755
756   obj->Set(errno_symbol, Integer::New(errorno));
757   if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
758   return e;
759 }
760
761
762 enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
763   HandleScope scope;
764
765   if (!encoding_v->IsString()) return _default;
766
767   String::Utf8Value encoding(encoding_v->ToString());
768
769   if (strcasecmp(*encoding, "utf8") == 0) {
770     return UTF8;
771   } else if (strcasecmp(*encoding, "utf-8") == 0) {
772     return UTF8;
773   } else if (strcasecmp(*encoding, "ascii") == 0) {
774     return ASCII;
775   } else if (strcasecmp(*encoding, "binary") == 0) {
776     return BINARY;
777   } else if (strcasecmp(*encoding, "raw") == 0) {
778     fprintf(stderr, "'raw' (array of integers) has been removed. "
779                     "Use 'binary'.\n");
780     return BINARY;
781   } else if (strcasecmp(*encoding, "raws") == 0) {
782     fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
783                     "Please update your code.\n");
784     return BINARY;
785   } else {
786     return _default;
787   }
788 }
789
790 Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
791   HandleScope scope;
792
793   if (!len) return scope.Close(String::Empty());
794
795   if (encoding == BINARY) {
796     const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
797     uint16_t * twobytebuf = new uint16_t[len];
798     for (size_t i = 0; i < len; i++) {
799       // XXX is the following line platform independent?
800       twobytebuf[i] = cbuf[i];
801     }
802     Local<String> chunk = String::New(twobytebuf, len);
803     delete [] twobytebuf; // TODO use ExternalTwoByteString?
804     return scope.Close(chunk);
805   }
806
807   // utf8 or ascii encoding
808   Local<String> chunk = String::New((const char*)buf, len);
809   return scope.Close(chunk);
810 }
811
812 // Returns -1 if the handle was not valid for decoding
813 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
814   HandleScope scope;
815
816   if (val->IsArray()) {
817     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
818                     "Use 'binary'.\n");
819     assert(0);
820     return -1;
821   }
822
823   Local<String> str = val->ToString();
824
825   if (encoding == UTF8) return str->Utf8Length();
826
827   return str->Length();
828 }
829
830 #ifndef MIN
831 # define MIN(a, b) ((a) < (b) ? (a) : (b))
832 #endif
833
834 // Returns number of bytes written.
835 ssize_t DecodeWrite(char *buf,
836                     size_t buflen,
837                     v8::Handle<v8::Value> val,
838                     enum encoding encoding) {
839   HandleScope scope;
840
841   // XXX
842   // A lot of improvement can be made here. See:
843   // http://code.google.com/p/v8/issues/detail?id=270
844   // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
845   // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
846
847   if (val->IsArray()) {
848     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
849                     "Use 'binary'.\n");
850     assert(0);
851     return -1;
852   }
853
854   Local<String> str = val->ToString();
855
856   if (encoding == UTF8) {
857     str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
858     return buflen;
859   }
860
861   if (encoding == ASCII) {
862     str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
863     return buflen;
864   }
865
866   // THIS IS AWFUL!!! FIXME
867
868   assert(encoding == BINARY);
869
870   uint16_t * twobytebuf = new uint16_t[buflen];
871
872   str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
873
874   for (size_t i = 0; i < buflen; i++) {
875     unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
876     assert(b[1] == 0);
877     buf[i] = b[0];
878   }
879
880   delete [] twobytebuf;
881
882   return buflen;
883 }
884
885 static Persistent<FunctionTemplate> stats_constructor_template;
886
887 Local<Object> BuildStatsObject(struct stat * s) {
888   HandleScope scope;
889
890   if (dev_symbol.IsEmpty()) {
891     dev_symbol = NODE_PSYMBOL("dev");
892     ino_symbol = NODE_PSYMBOL("ino");
893     mode_symbol = NODE_PSYMBOL("mode");
894     nlink_symbol = NODE_PSYMBOL("nlink");
895     uid_symbol = NODE_PSYMBOL("uid");
896     gid_symbol = NODE_PSYMBOL("gid");
897     rdev_symbol = NODE_PSYMBOL("rdev");
898     size_symbol = NODE_PSYMBOL("size");
899     blksize_symbol = NODE_PSYMBOL("blksize");
900     blocks_symbol = NODE_PSYMBOL("blocks");
901     atime_symbol = NODE_PSYMBOL("atime");
902     mtime_symbol = NODE_PSYMBOL("mtime");
903     ctime_symbol = NODE_PSYMBOL("ctime");
904   }
905
906   Local<Object> stats =
907     stats_constructor_template->GetFunction()->NewInstance();
908
909   /* ID of device containing file */
910   stats->Set(dev_symbol, Integer::New(s->st_dev));
911
912   /* inode number */
913   stats->Set(ino_symbol, Integer::New(s->st_ino));
914
915   /* protection */
916   stats->Set(mode_symbol, Integer::New(s->st_mode));
917
918   /* number of hard links */
919   stats->Set(nlink_symbol, Integer::New(s->st_nlink));
920
921   /* user ID of owner */
922   stats->Set(uid_symbol, Integer::New(s->st_uid));
923
924   /* group ID of owner */
925   stats->Set(gid_symbol, Integer::New(s->st_gid));
926
927   /* device ID (if special file) */
928   stats->Set(rdev_symbol, Integer::New(s->st_rdev));
929
930   /* total size, in bytes */
931   stats->Set(size_symbol, Number::New(s->st_size));
932
933   /* blocksize for filesystem I/O */
934   stats->Set(blksize_symbol, Integer::New(s->st_blksize));
935
936   /* number of blocks allocated */
937   stats->Set(blocks_symbol, Integer::New(s->st_blocks));
938
939   /* time of last access */
940   stats->Set(atime_symbol, NODE_UNIXTIME_V8(s->st_atime));
941
942   /* time of last modification */
943   stats->Set(mtime_symbol, NODE_UNIXTIME_V8(s->st_mtime));
944
945   /* time of last status change */
946   stats->Set(ctime_symbol, NODE_UNIXTIME_V8(s->st_ctime));
947
948   return scope.Close(stats);
949 }
950
951
952 // Extracts a C str from a V8 Utf8Value.
953 const char* ToCString(const v8::String::Utf8Value& value) {
954   return *value ? *value : "<str conversion failed>";
955 }
956
957 static void ReportException(TryCatch &try_catch, bool show_line) {
958   Handle<Message> message = try_catch.Message();
959
960   Handle<Value> error = try_catch.Exception();
961   Handle<String> stack;
962
963   if (error->IsObject()) {
964     Handle<Object> obj = Handle<Object>::Cast(error);
965     Handle<Value> raw_stack = obj->Get(String::New("stack"));
966     if (raw_stack->IsString()) stack = Handle<String>::Cast(raw_stack);
967   }
968
969   if (show_line && !message.IsEmpty()) {
970     // Print (filename):(line number): (message).
971     String::Utf8Value filename(message->GetScriptResourceName());
972     const char* filename_string = ToCString(filename);
973     int linenum = message->GetLineNumber();
974     fprintf(stderr, "%s:%i\n", filename_string, linenum);
975     // Print line of source code.
976     String::Utf8Value sourceline(message->GetSourceLine());
977     const char* sourceline_string = ToCString(sourceline);
978
979     // HACK HACK HACK
980     //
981     // FIXME
982     //
983     // Because of how CommonJS modules work, all scripts are wrapped with a
984     // "function (function (exports, __filename, ...) {"
985     // to provide script local variables.
986     //
987     // When reporting errors on the first line of a script, this wrapper
988     // function is leaked to the user. This HACK is to remove it. The length
989     // of the wrapper is 62. That wrapper is defined in lib/module.js
990     //
991     // If that wrapper is ever changed, then this number also has to be
992     // updated. Or - someone could clean this up so that the two peices
993     // don't need to be changed.
994     //
995     // Even better would be to get support into V8 for wrappers that
996     // shouldn't be reported to users.
997     int offset = linenum == 1 ? 62 : 0;
998
999     fprintf(stderr, "%s\n", sourceline_string + offset);
1000     // Print wavy underline (GetUnderline is deprecated).
1001     int start = message->GetStartColumn();
1002     for (int i = offset; i < start; i++) {
1003       fprintf(stderr, " ");
1004     }
1005     int end = message->GetEndColumn();
1006     for (int i = start; i < end; i++) {
1007       fprintf(stderr, "^");
1008     }
1009     fprintf(stderr, "\n");
1010   }
1011
1012   if (stack.IsEmpty()) {
1013     message->PrintCurrentStackTrace(stderr);
1014   } else {
1015     String::Utf8Value trace(stack);
1016     fprintf(stderr, "%s\n", *trace);
1017   }
1018   fflush(stderr);
1019 }
1020
1021 // Executes a str within the current v8 context.
1022 Local<Value> ExecuteString(Local<String> source, Local<Value> filename) {
1023   HandleScope scope;
1024   TryCatch try_catch;
1025
1026   Local<v8::Script> script = v8::Script::Compile(source, filename);
1027   if (script.IsEmpty()) {
1028     ReportException(try_catch, true);
1029     exit(1);
1030   }
1031
1032   Local<Value> result = script->Run();
1033   if (result.IsEmpty()) {
1034     ReportException(try_catch, true);
1035     exit(1);
1036   }
1037
1038   return scope.Close(result);
1039 }
1040
1041 static Handle<Value> ByteLength(const Arguments& args) {
1042   HandleScope scope;
1043
1044   if (args.Length() < 1 || !args[0]->IsString()) {
1045     return ThrowException(Exception::Error(String::New("Bad argument.")));
1046   }
1047
1048   Local<Integer> length = Integer::New(DecodeBytes(args[0], ParseEncoding(args[1], UTF8)));
1049
1050   return scope.Close(length);
1051 }
1052
1053 static Handle<Value> Loop(const Arguments& args) {
1054   HandleScope scope;
1055   assert(args.Length() == 0);
1056
1057   // TODO Probably don't need to start this each time.
1058   // Avoids failing on test/mjsunit/test-eio-race3.js though
1059   ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
1060
1061   ev_loop(EV_DEFAULT_UC_ 0);
1062   return Undefined();
1063 }
1064
1065 static Handle<Value> Unloop(const Arguments& args) {
1066   fprintf(stderr, "Deprecation: Don't use process.unloop(). It will be removed soon.\n");
1067   HandleScope scope;
1068   int how = EVUNLOOP_ONE;
1069   if (args[0]->IsString()) {
1070     String::Utf8Value how_s(args[0]->ToString());
1071     if (0 == strcmp(*how_s, "all")) {
1072       how = EVUNLOOP_ALL;
1073     }
1074   }
1075   ev_unloop(EV_DEFAULT_ how);
1076   return Undefined();
1077 }
1078
1079 static Handle<Value> Chdir(const Arguments& args) {
1080   HandleScope scope;
1081
1082   if (args.Length() != 1 || !args[0]->IsString()) {
1083     return ThrowException(Exception::Error(String::New("Bad argument.")));
1084   }
1085
1086   String::Utf8Value path(args[0]->ToString());
1087
1088   int r = chdir(*path);
1089
1090   if (r != 0) {
1091     return ThrowException(Exception::Error(String::New(strerror(errno))));
1092   }
1093
1094   return Undefined();
1095 }
1096
1097 static Handle<Value> Cwd(const Arguments& args) {
1098   HandleScope scope;
1099   assert(args.Length() == 0);
1100
1101   char output[PATH_MAX];
1102   char *r = getcwd(output, PATH_MAX);
1103   if (r == NULL) {
1104     return ThrowException(Exception::Error(String::New(strerror(errno))));
1105   }
1106   Local<String> cwd = String::New(output);
1107
1108   return scope.Close(cwd);
1109 }
1110
1111 static Handle<Value> Umask(const Arguments& args){
1112   HandleScope scope;
1113   unsigned int old;
1114   if(args.Length() < 1) {
1115     old = umask(0);
1116     umask((mode_t)old);
1117   }
1118   else if(!args[0]->IsInt32()) {
1119     return ThrowException(Exception::TypeError(
1120           String::New("argument must be an integer.")));
1121   }
1122   else {
1123     old = umask((mode_t)args[0]->Uint32Value());
1124   }
1125   return scope.Close(Uint32::New(old));
1126 }
1127
1128
1129 static Handle<Value> GetUid(const Arguments& args) {
1130   HandleScope scope;
1131   assert(args.Length() == 0);
1132   int uid = getuid();
1133   return scope.Close(Integer::New(uid));
1134 }
1135
1136 static Handle<Value> GetGid(const Arguments& args) {
1137   HandleScope scope;
1138   assert(args.Length() == 0);
1139   int gid = getgid();
1140   return scope.Close(Integer::New(gid));
1141 }
1142
1143
1144 static Handle<Value> SetGid(const Arguments& args) {
1145   HandleScope scope;
1146
1147   if (args.Length() < 1) {
1148     return ThrowException(Exception::Error(
1149       String::New("setgid requires 1 argument")));
1150   }
1151
1152   Local<Integer> given_gid = args[0]->ToInteger();
1153   int gid = given_gid->Int32Value();
1154   int result;
1155   if ((result = setgid(gid)) != 0) {
1156     return ThrowException(Exception::Error(String::New(strerror(errno))));
1157   }
1158   return Undefined();
1159 }
1160
1161 static Handle<Value> SetUid(const Arguments& args) {
1162   HandleScope scope;
1163
1164   if (args.Length() < 1) {
1165     return ThrowException(Exception::Error(
1166           String::New("setuid requires 1 argument")));
1167   }
1168
1169   Local<Integer> given_uid = args[0]->ToInteger();
1170   int uid = given_uid->Int32Value();
1171   int result;
1172   if ((result = setuid(uid)) != 0) {
1173     return ThrowException(Exception::Error(String::New(strerror(errno))));
1174   }
1175   return Undefined();
1176 }
1177
1178
1179 v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
1180   HandleScope scope;
1181   fflush(stderr);
1182   Stdio::Flush();
1183   exit(args[0]->IntegerValue());
1184   return Undefined();
1185 }
1186
1187 #ifdef __sun
1188 #define HAVE_GETMEM 1
1189 #include <unistd.h> /* getpagesize() */
1190
1191 #if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
1192 #define PROCFS_FILE_OFFSET_BITS_HACK 1
1193 #undef _FILE_OFFSET_BITS
1194 #else
1195 #define PROCFS_FILE_OFFSET_BITS_HACK 0
1196 #endif
1197
1198 #include <procfs.h>
1199
1200 #if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1)
1201 #define _FILE_OFFSET_BITS 64
1202 #endif
1203
1204 int getmem(size_t *rss, size_t *vsize) {
1205   pid_t pid = getpid();
1206
1207   size_t page_size = getpagesize();
1208   char pidpath[1024];
1209   sprintf(pidpath, "/proc/%d/psinfo", pid);
1210
1211   psinfo_t psinfo;
1212   FILE *f = fopen(pidpath, "r");
1213   if (!f) return -1;
1214
1215   if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) {
1216     fclose (f);
1217     return -1;
1218   }
1219
1220   /* XXX correct? */
1221
1222   *vsize = (size_t) psinfo.pr_size * page_size;
1223   *rss = (size_t) psinfo.pr_rssize * 1024;
1224
1225   fclose (f);
1226
1227   return 0;
1228 }
1229 #endif
1230
1231
1232 #ifdef __FreeBSD__
1233 #define HAVE_GETMEM 1
1234 #include <kvm.h>
1235 #include <sys/param.h>
1236 #include <sys/sysctl.h>
1237 #include <sys/user.h>
1238 #include <paths.h>
1239 #include <fcntl.h>
1240 #include <unistd.h>
1241
1242 int getmem(size_t *rss, size_t *vsize) {
1243   kvm_t *kd = NULL;
1244   struct kinfo_proc *kinfo = NULL;
1245   pid_t pid;
1246   int nprocs;
1247   size_t page_size = getpagesize();
1248
1249   pid = getpid();
1250
1251   kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
1252   if (kd == NULL) goto error;
1253
1254   kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs);
1255   if (kinfo == NULL) goto error;
1256
1257   *rss = kinfo->ki_rssize * page_size;
1258   *vsize = kinfo->ki_size;
1259
1260   kvm_close(kd);
1261
1262   return 0;
1263
1264 error:
1265   if (kd) kvm_close(kd);
1266   return -1;
1267 }
1268 #endif  // __FreeBSD__
1269
1270
1271 #ifdef __APPLE__
1272 #define HAVE_GETMEM 1
1273 /* Researched by Tim Becker and Michael Knight
1274  * http://blog.kuriositaet.de/?p=257
1275  */
1276
1277 #include <mach/task.h>
1278 #include <mach/mach_init.h>
1279
1280 int getmem(size_t *rss, size_t *vsize) {
1281   struct task_basic_info t_info;
1282   mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
1283
1284   int r = task_info(mach_task_self(),
1285                     TASK_BASIC_INFO,
1286                     (task_info_t)&t_info,
1287                     &t_info_count);
1288
1289   if (r != KERN_SUCCESS) return -1;
1290
1291   *rss = t_info.resident_size;
1292   *vsize  = t_info.virtual_size;
1293
1294   return 0;
1295 }
1296 #endif  // __APPLE__
1297
1298 #ifdef __linux__
1299 # define HAVE_GETMEM 1
1300 # include <sys/param.h> /* for MAXPATHLEN */
1301
1302 int getmem(size_t *rss, size_t *vsize) {
1303   FILE *f = fopen("/proc/self/stat", "r");
1304   if (!f) return -1;
1305
1306   int itmp;
1307   char ctmp;
1308   char buffer[MAXPATHLEN];
1309   size_t page_size = getpagesize();
1310
1311   /* PID */
1312   if (fscanf(f, "%d ", &itmp) == 0) goto error;
1313   /* Exec file */
1314   if (fscanf (f, "%s ", &buffer[0]) == 0) goto error;
1315   /* State */
1316   if (fscanf (f, "%c ", &ctmp) == 0) goto error;
1317   /* Parent process */
1318   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1319   /* Process group */
1320   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1321   /* Session id */
1322   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1323   /* TTY */
1324   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1325   /* TTY owner process group */
1326   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1327   /* Flags */
1328   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1329   /* Minor faults (no memory page) */
1330   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1331   /* Minor faults, children */
1332   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1333   /* Major faults (memory page faults) */
1334   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1335   /* Major faults, children */
1336   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1337   /* utime */
1338   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1339   /* stime */
1340   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1341   /* utime, children */
1342   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1343   /* stime, children */
1344   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1345   /* jiffies remaining in current time slice */
1346   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1347   /* 'nice' value */
1348   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1349   /* jiffies until next timeout */
1350   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1351   /* jiffies until next SIGALRM */
1352   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1353   /* start time (jiffies since system boot) */
1354   if (fscanf (f, "%d ", &itmp) == 0) goto error;
1355
1356   /* Virtual memory size */
1357   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1358   *vsize = (size_t) itmp;
1359
1360   /* Resident set size */
1361   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1362   *rss = (size_t) itmp * page_size;
1363
1364   /* rlim */
1365   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1366   /* Start of text */
1367   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1368   /* End of text */
1369   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1370   /* Start of stack */
1371   if (fscanf (f, "%u ", &itmp) == 0) goto error;
1372
1373   fclose (f);
1374
1375   return 0;
1376
1377 error:
1378   fclose (f);
1379   return -1;
1380 }
1381 #endif  // __linux__
1382
1383
1384 static void CheckStatus(EV_P_ ev_timer *watcher, int revents) {
1385   assert(watcher == &gc_timer);
1386   assert(revents == EV_TIMER);
1387
1388 #if HAVE_GETMEM
1389   // check memory
1390   size_t rss, vsize;
1391   if (!ev_is_active(&gc_idle) && getmem(&rss, &vsize) == 0) {
1392     if (rss > 1024*1024*128) {
1393       // larger than 128 megs, just start the idle watcher
1394       ev_idle_start(EV_A_ &gc_idle);
1395       return;
1396     }
1397   }
1398 #endif // HAVE_GETMEM
1399
1400   double d = ev_now() - TICK_TIME(3);
1401
1402   //printfb("timer d = %f\n", d);
1403
1404   if (d  >= GC_WAIT_TIME - 1.) {
1405     //fprintf(stderr, "start idle\n");
1406     ev_idle_start(EV_A_ &gc_idle);
1407   }
1408 }
1409
1410
1411 v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1412   HandleScope scope;
1413   assert(args.Length() == 0);
1414
1415 #ifndef HAVE_GETMEM
1416   return ThrowException(Exception::Error(String::New("Not support on your platform. (Talk to Ryan.)")));
1417 #else
1418   size_t rss, vsize;
1419
1420   int r = getmem(&rss, &vsize);
1421
1422   if (r != 0) {
1423     return ThrowException(Exception::Error(String::New(strerror(errno))));
1424   }
1425
1426   Local<Object> info = Object::New();
1427
1428   if (rss_symbol.IsEmpty()) {
1429     rss_symbol = NODE_PSYMBOL("rss");
1430     vsize_symbol = NODE_PSYMBOL("vsize");
1431     heap_total_symbol = NODE_PSYMBOL("heapTotal");
1432     heap_used_symbol = NODE_PSYMBOL("heapUsed");
1433   }
1434
1435   info->Set(rss_symbol, Integer::NewFromUnsigned(rss));
1436   info->Set(vsize_symbol, Integer::NewFromUnsigned(vsize));
1437
1438   // V8 memory usage
1439   HeapStatistics v8_heap_stats;
1440   V8::GetHeapStatistics(&v8_heap_stats);
1441   info->Set(heap_total_symbol,
1442             Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
1443   info->Set(heap_used_symbol,
1444             Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1445
1446   return scope.Close(info);
1447 #endif
1448 }
1449
1450
1451 v8::Handle<v8::Value> Kill(const v8::Arguments& args) {
1452   HandleScope scope;
1453
1454   if (args.Length() < 1 || !args[0]->IsNumber()) {
1455     return ThrowException(Exception::Error(String::New("Bad argument.")));
1456   }
1457
1458   pid_t pid = args[0]->IntegerValue();
1459
1460   int sig = SIGTERM;
1461
1462   if (args.Length() >= 2) {
1463     if (args[1]->IsNumber()) {
1464       sig = args[1]->Int32Value();
1465     } else if (args[1]->IsString()) {
1466       Local<String> signame = args[1]->ToString();
1467
1468       Local<Value> sig_v = process->Get(signame);
1469       if (!sig_v->IsNumber()) {
1470         return ThrowException(Exception::Error(String::New("Unknown signal")));
1471       }
1472       sig = sig_v->Int32Value();
1473     }
1474   }
1475
1476   int r = kill(pid, sig);
1477
1478   if (r != 0) {
1479     return ThrowException(Exception::Error(String::New(strerror(errno))));
1480   }
1481
1482   return Undefined();
1483 }
1484
1485 typedef void (*extInit)(Handle<Object> exports);
1486
1487 // DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1488 // objects.
1489 Handle<Value> DLOpen(const v8::Arguments& args) {
1490   HandleScope scope;
1491
1492   if (args.Length() < 2) return Undefined();
1493
1494   String::Utf8Value filename(args[0]->ToString()); // Cast
1495   Local<Object> target = args[1]->ToObject(); // Cast
1496
1497   // Actually call dlopen().
1498   // FIXME: This is a blocking function and should be called asynchronously!
1499   // This function should be moved to file.cc and use libeio to make this
1500   // system call.
1501   void *handle = dlopen(*filename, RTLD_LAZY);
1502
1503   // Handle errors.
1504   if (handle == NULL) {
1505     Local<Value> exception = Exception::Error(String::New(dlerror()));
1506     return ThrowException(exception);
1507   }
1508
1509   // Get the init() function from the dynamically shared object.
1510   void *init_handle = dlsym(handle, "init");
1511   // Error out if not found.
1512   if (init_handle == NULL) {
1513     Local<Value> exception =
1514       Exception::Error(String::New("No 'init' symbol found in module."));
1515     return ThrowException(exception);
1516   }
1517   extInit init = (extInit)(init_handle); // Cast
1518
1519   // Execute the C++ module
1520   init(target);
1521
1522   return Undefined();
1523 }
1524
1525
1526 Handle<Value> Compile(const Arguments& args) {
1527   HandleScope scope;
1528
1529   if (args.Length() < 2) {
1530     return ThrowException(Exception::TypeError(
1531           String::New("needs two arguments.")));
1532   }
1533
1534   Local<String> source = args[0]->ToString();
1535   Local<String> filename = args[1]->ToString();
1536
1537   TryCatch try_catch;
1538
1539   Local<v8::Script> script = v8::Script::Compile(source, filename);
1540   if (try_catch.HasCaught()) {
1541     // Hack because I can't get a proper stacktrace on SyntaxError
1542     ReportException(try_catch, true);
1543     exit(1);
1544   }
1545
1546   Local<Value> result = script->Run();
1547   if (try_catch.HasCaught()) {
1548     ReportException(try_catch, false);
1549     exit(1);
1550   }
1551
1552   return scope.Close(result);
1553 }
1554
1555 static void OnFatalError(const char* location, const char* message) {
1556   if (location) {
1557     fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1558   } else {
1559     fprintf(stderr, "FATAL ERROR: %s\n", message);
1560   }
1561   exit(1);
1562 }
1563
1564 static int uncaught_exception_counter = 0;
1565
1566 void FatalException(TryCatch &try_catch) {
1567   HandleScope scope;
1568
1569   // Check if uncaught_exception_counter indicates a recursion
1570   if (uncaught_exception_counter > 0) {
1571     ReportException(try_catch, true);
1572     exit(1);
1573   }
1574
1575   if (listeners_symbol.IsEmpty()) {
1576     listeners_symbol = NODE_PSYMBOL("listeners");
1577     uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1578     emit_symbol = NODE_PSYMBOL("emit");
1579   }
1580
1581   Local<Value> listeners_v = process->Get(listeners_symbol);
1582   assert(listeners_v->IsFunction());
1583
1584   Local<Function> listeners = Local<Function>::Cast(listeners_v);
1585
1586   Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1587   Local<Value> argv[1] = { uncaught_exception_symbol_l  };
1588   Local<Value> ret = listeners->Call(process, 1, argv);
1589
1590   assert(ret->IsArray());
1591
1592   Local<Array> listener_array = Local<Array>::Cast(ret);
1593
1594   uint32_t length = listener_array->Length();
1595   // Report and exit if process has no "uncaughtException" listener
1596   if (length == 0) {
1597     ReportException(try_catch, true);
1598     exit(1);
1599   }
1600
1601   // Otherwise fire the process "uncaughtException" event
1602   Local<Value> emit_v = process->Get(emit_symbol);
1603   assert(emit_v->IsFunction());
1604
1605   Local<Function> emit = Local<Function>::Cast(emit_v);
1606
1607   Local<Value> error = try_catch.Exception();
1608   Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
1609
1610   uncaught_exception_counter++;
1611   emit->Call(process, 2, event_argv);
1612   // Decrement so we know if the next exception is a recursion or not
1613   uncaught_exception_counter--;
1614 }
1615
1616
1617 static ev_async debug_watcher;
1618 volatile static bool debugger_msg_pending = false;
1619
1620 static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) {
1621   HandleScope scope;
1622   assert(watcher == &debug_watcher);
1623   assert(revents == EV_ASYNC);
1624   Debug::ProcessDebugMessages();
1625 }
1626
1627 static void DebugMessageDispatch(void) {
1628   // This function is called from V8's debug thread when a debug TCP client
1629   // has sent a message.
1630
1631   // Send a signal to our main thread saying that it should enter V8 to
1632   // handle the message.
1633   debugger_msg_pending = true;
1634   ev_async_send(EV_DEFAULT_UC_ &debug_watcher);
1635 }
1636
1637 static Handle<Value> CheckBreak(const Arguments& args) {
1638   HandleScope scope;
1639   assert(args.Length() == 0);
1640
1641   // TODO FIXME This function is a hack to wait until V8 is ready to accept
1642   // commands. There seems to be a bug in EnableAgent( _ , _ , true) which
1643   // makes it unusable here. Ideally we'd be able to bind EnableAgent and
1644   // get it to halt until Eclipse connects.
1645
1646   if (!debug_wait_connect)
1647     return Undefined();
1648
1649   printf("Waiting for remote debugger connection...\n");
1650
1651   const int halfSecond = 50;
1652   const int tenMs=10000;
1653   debugger_msg_pending = false;
1654   for (;;) {
1655     if (debugger_msg_pending) {
1656       Debug::DebugBreak();
1657       Debug::ProcessDebugMessages();
1658       debugger_msg_pending = false;
1659
1660       // wait for 500 msec of silence from remote debugger
1661       int cnt = halfSecond;
1662         while (cnt --) {
1663         debugger_msg_pending = false;
1664         usleep(tenMs);
1665         if (debugger_msg_pending) {
1666           debugger_msg_pending = false;
1667           cnt = halfSecond;
1668         }
1669       }
1670       break;
1671     }
1672     usleep(tenMs);
1673   }
1674   return Undefined();
1675 }
1676
1677 Persistent<Object> binding_cache;
1678
1679 static Handle<Value> Binding(const Arguments& args) {
1680   HandleScope scope;
1681
1682   Local<String> module = args[0]->ToString();
1683   String::Utf8Value module_v(module);
1684
1685   if (binding_cache.IsEmpty()) {
1686     binding_cache = Persistent<Object>::New(Object::New());
1687   }
1688
1689   Local<Object> exports;
1690
1691   // TODO DRY THIS UP!
1692
1693   if (!strcmp(*module_v, "stdio")) {
1694     if (binding_cache->Has(module)) {
1695       exports = binding_cache->Get(module)->ToObject();
1696     } else {
1697       exports = Object::New();
1698       Stdio::Initialize(exports);
1699       binding_cache->Set(module, exports);
1700     }
1701
1702   } else if (!strcmp(*module_v, "cares")) {
1703     if (binding_cache->Has(module)) {
1704       exports = binding_cache->Get(module)->ToObject();
1705     } else {
1706       exports = Object::New();
1707       Cares::Initialize(exports);
1708       binding_cache->Set(module, exports);
1709     }
1710
1711   } else if (!strcmp(*module_v, "fs")) {
1712     if (binding_cache->Has(module)) {
1713       exports = binding_cache->Get(module)->ToObject();
1714     } else {
1715       exports = Object::New();
1716
1717       // Initialize the stats object
1718       Local<FunctionTemplate> stat_templ = FunctionTemplate::New();
1719       stats_constructor_template = Persistent<FunctionTemplate>::New(stat_templ);
1720       exports->Set(String::NewSymbol("Stats"),
1721                    stats_constructor_template->GetFunction());
1722       StatWatcher::Initialize(exports);
1723       File::Initialize(exports);
1724       binding_cache->Set(module, exports);
1725     }
1726
1727   } else if (!strcmp(*module_v, "signal_watcher")) {
1728     if (binding_cache->Has(module)) {
1729       exports = binding_cache->Get(module)->ToObject();
1730     } else {
1731       exports = Object::New();
1732       SignalWatcher::Initialize(exports);
1733       binding_cache->Set(module, exports);
1734     }
1735
1736   } else if (!strcmp(*module_v, "net")) {
1737     if (binding_cache->Has(module)) {
1738       exports = binding_cache->Get(module)->ToObject();
1739     } else {
1740       exports = Object::New();
1741       InitNet2(exports);
1742       binding_cache->Set(module, exports);
1743     }
1744
1745   } else if (!strcmp(*module_v, "http_parser")) {
1746     if (binding_cache->Has(module)) {
1747       exports = binding_cache->Get(module)->ToObject();
1748     } else {
1749       exports = Object::New();
1750       InitHttpParser(exports);
1751       binding_cache->Set(module, exports);
1752     }
1753
1754   } else if (!strcmp(*module_v, "child_process")) {
1755     if (binding_cache->Has(module)) {
1756       exports = binding_cache->Get(module)->ToObject();
1757     } else {
1758       exports = Object::New();
1759       ChildProcess::Initialize(exports);
1760       binding_cache->Set(module, exports);
1761     }
1762
1763   } else if (!strcmp(*module_v, "buffer")) {
1764     if (binding_cache->Has(module)) {
1765       exports = binding_cache->Get(module)->ToObject();
1766     } else {
1767       exports = Object::New();
1768       Buffer::Initialize(exports);
1769       binding_cache->Set(module, exports);
1770     }
1771   #ifdef HAVE_OPENSSL
1772   } else if (!strcmp(*module_v, "crypto")) {
1773     if (binding_cache->Has(module)) {
1774       exports = binding_cache->Get(module)->ToObject();
1775     } else {
1776       exports = Object::New();
1777       InitCrypto(exports);
1778       binding_cache->Set(module, exports);
1779     }
1780   #endif
1781   } else if (!strcmp(*module_v, "evals")) {
1782     if (binding_cache->Has(module)) {
1783       exports = binding_cache->Get(module)->ToObject();
1784     } else {
1785       exports = Object::New();
1786       node::Script::Initialize(exports);
1787       binding_cache->Set(module, exports);
1788     }
1789
1790   } else if (!strcmp(*module_v, "natives")) {
1791     if (binding_cache->Has(module)) {
1792       exports = binding_cache->Get(module)->ToObject();
1793     } else {
1794       exports = Object::New();
1795       // Explicitly define native sources.
1796       // TODO DRY/automate this?
1797       exports->Set(String::New("assert"),       String::New(native_assert));
1798       exports->Set(String::New("buffer"),       String::New(native_buffer));
1799       exports->Set(String::New("child_process"),String::New(native_child_process));
1800       exports->Set(String::New("dns"),          String::New(native_dns));
1801       exports->Set(String::New("events"),       String::New(native_events));
1802       exports->Set(String::New("file"),         String::New(native_file));
1803       exports->Set(String::New("freelist"),     String::New(native_freelist));
1804       exports->Set(String::New("fs"),           String::New(native_fs));
1805       exports->Set(String::New("http"),         String::New(native_http));
1806       exports->Set(String::New("crypto"),       String::New(native_crypto));
1807       exports->Set(String::New("ini"),          String::New(native_ini));
1808       exports->Set(String::New("mjsunit"),      String::New(native_mjsunit));
1809       exports->Set(String::New("net"),          String::New(native_net));
1810       exports->Set(String::New("posix"),        String::New(native_posix));
1811       exports->Set(String::New("querystring"),  String::New(native_querystring));
1812       exports->Set(String::New("repl"),         String::New(native_repl));
1813       exports->Set(String::New("sys"),          String::New(native_sys));
1814       exports->Set(String::New("tcp"),          String::New(native_tcp));
1815       exports->Set(String::New("uri"),          String::New(native_uri));
1816       exports->Set(String::New("url"),          String::New(native_url));
1817       exports->Set(String::New("utils"),        String::New(native_utils));
1818       exports->Set(String::New("path"),         String::New(native_path));
1819       exports->Set(String::New("module"),       String::New(native_module));
1820       binding_cache->Set(module, exports);
1821     }
1822
1823   } else {
1824     return ThrowException(Exception::Error(String::New("No such module")));
1825   }
1826
1827   return scope.Close(exports);
1828 }
1829
1830
1831 static void Load(int argc, char *argv[]) {
1832   HandleScope scope;
1833
1834   Local<FunctionTemplate> process_template = FunctionTemplate::New();
1835   node::EventEmitter::Initialize(process_template);
1836
1837   process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
1838
1839   // Add a reference to the global object
1840   Local<Object> global = Context::GetCurrent()->Global();
1841   process->Set(String::NewSymbol("global"), global);
1842
1843   // process.version
1844   process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
1845   // process.installPrefix
1846   process->Set(String::NewSymbol("installPrefix"), String::New(NODE_PREFIX));
1847
1848   // process.platform
1849 #define xstr(s) str(s)
1850 #define str(s) #s
1851   process->Set(String::NewSymbol("platform"), String::New(xstr(PLATFORM)));
1852
1853   // process.argv
1854   int i, j;
1855   Local<Array> arguments = Array::New(argc - option_end_index + 1);
1856   arguments->Set(Integer::New(0), String::New(argv[0]));
1857   for (j = 1, i = option_end_index + 1; i < argc; j++, i++) {
1858     Local<String> arg = String::New(argv[i]);
1859     arguments->Set(Integer::New(j), arg);
1860   }
1861   // assign it
1862   process->Set(String::NewSymbol("ARGV"), arguments);
1863   process->Set(String::NewSymbol("argv"), arguments);
1864
1865   // create process.env
1866   Local<Object> env = Object::New();
1867   for (i = 0; environ[i]; i++) {
1868     // skip entries without a '=' character
1869     for (j = 0; environ[i][j] && environ[i][j] != '='; j++) { ; }
1870     // create the v8 objects
1871     Local<String> field = String::New(environ[i], j);
1872     Local<String> value = Local<String>();
1873     if (environ[i][j] == '=') {
1874       value = String::New(environ[i]+j+1);
1875     }
1876     // assign them
1877     env->Set(field, value);
1878   }
1879   // assign process.ENV
1880   process->Set(String::NewSymbol("ENV"), env);
1881   process->Set(String::NewSymbol("env"), env);
1882
1883   process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
1884
1885   // define various internal methods
1886   NODE_SET_METHOD(process, "loop", Loop);
1887   NODE_SET_METHOD(process, "unloop", Unloop);
1888   NODE_SET_METHOD(process, "compile", Compile);
1889   NODE_SET_METHOD(process, "_byteLength", ByteLength);
1890   NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
1891   NODE_SET_METHOD(process, "reallyExit", Exit);
1892   NODE_SET_METHOD(process, "chdir", Chdir);
1893   NODE_SET_METHOD(process, "cwd", Cwd);
1894   NODE_SET_METHOD(process, "getuid", GetUid);
1895   NODE_SET_METHOD(process, "setuid", SetUid);
1896
1897   NODE_SET_METHOD(process, "setgid", SetGid);
1898   NODE_SET_METHOD(process, "getgid", GetGid);
1899
1900   NODE_SET_METHOD(process, "umask", Umask);
1901   NODE_SET_METHOD(process, "dlopen", DLOpen);
1902   NODE_SET_METHOD(process, "kill", Kill);
1903   NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
1904   NODE_SET_METHOD(process, "checkBreak", CheckBreak);
1905
1906   NODE_SET_METHOD(process, "binding", Binding);
1907
1908   // Assign the EventEmitter. It was created in main().
1909   process->Set(String::NewSymbol("EventEmitter"),
1910                EventEmitter::constructor_template->GetFunction());
1911
1912
1913   // Initialize the C++ modules..................filename of module
1914   IOWatcher::Initialize(process);              // io_watcher.cc
1915   // Not in use at the moment.
1916   //IdleWatcher::Initialize(process);            // idle_watcher.cc
1917   Timer::Initialize(process);                  // timer.cc
1918   DefineConstants(process);                    // constants.cc
1919
1920   // Compile, execute the src/node.js file. (Which was included as static C
1921   // string in node_natives.h. 'natve_node' is the string containing that
1922   // source code.)
1923
1924   // The node.js file returns a function 'f'
1925
1926   TryCatch try_catch;
1927
1928   Local<Value> f_value = ExecuteString(String::New(native_node),
1929                                        String::New("node.js"));
1930   if (try_catch.HasCaught())  {
1931     ReportException(try_catch, true);
1932     exit(10);
1933   }
1934   assert(f_value->IsFunction());
1935   Local<Function> f = Local<Function>::Cast(f_value);
1936
1937   // Now we call 'f' with the 'process' variable that we've built up with
1938   // all our bindings. Inside node.js we'll take care of assigning things to
1939   // their places.
1940
1941   // We start the process this way in order to be more modular. Developers
1942   // who do not like how 'src/node.js' setups the module system but do like
1943   // Node's I/O bindings may want to replace 'f' with their own function.
1944
1945   Local<Value> args[1] = { Local<Value>::New(process) };
1946
1947   f->Call(global, 1, args);
1948
1949   if (try_catch.HasCaught())  {
1950     ReportException(try_catch, true);
1951     exit(11);
1952   }
1953 }
1954
1955 static void PrintHelp();
1956
1957 static void ParseDebugOpt(const char* arg) {
1958   const char *p = 0;
1959
1960   use_debug_agent = true;
1961   if (!strcmp (arg, "--debug-brk")) {
1962     debug_wait_connect = true;
1963     return;
1964   } else if (!strcmp(arg, "--debug")) {
1965     return;
1966   } else if (strstr(arg, "--debug-brk=") == arg) {
1967     debug_wait_connect = true;
1968     p = 1 + strchr(arg, '=');
1969     debug_port = atoi(p);
1970   } else if (strstr(arg, "--debug=") == arg) {
1971     p = 1 + strchr(arg, '=');
1972     debug_port = atoi(p);
1973   }
1974   if (p && debug_port > 1024 && debug_port <  65536)
1975       return;
1976
1977   fprintf(stderr, "Bad debug option.\n");
1978   if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
1979
1980   PrintHelp();
1981   exit(1);
1982 }
1983
1984 static void PrintHelp() {
1985   printf("Usage: node [options] script.js [arguments] \n"
1986          "Options:\n"
1987          "  -v, --version      print node's version\n"
1988          "  --debug[=port]     enable remote debugging via given TCP port\n"
1989          "                     without stopping the execution\n"
1990          "  --debug-brk[=port] as above, but break in script.js and\n"
1991          "                     wait for remote debugger to connect\n"
1992          "  --v8-options       print v8 command line options\n"
1993          "  --vars             print various compiled-in variables\n"
1994          "\n"
1995          "Enviromental variables:\n"
1996          "NODE_PATH            ':'-separated list of directories\n"
1997          "                     prefixed to the module search path,\n"
1998          "                     require.paths.\n"
1999          "NODE_DEBUG           Print additional debugging output.\n"
2000          "\n"
2001          "Documentation can be found at http://nodejs.org/api.html"
2002          " or with 'man node'\n");
2003 }
2004
2005 // Parse node command line arguments.
2006 static void ParseArgs(int *argc, char **argv) {
2007   // TODO use parse opts
2008   for (int i = 1; i < *argc; i++) {
2009     const char *arg = argv[i];
2010     if (strstr(arg, "--debug") == arg) {
2011       ParseDebugOpt(arg);
2012       argv[i] = const_cast<char*>("");
2013       option_end_index = i;
2014     } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2015       printf("%s\n", NODE_VERSION);
2016       exit(0);
2017     } else if (strcmp(arg, "--vars") == 0) {
2018       printf("NODE_PREFIX: %s\n", NODE_PREFIX);
2019       printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
2020       exit(0);
2021     } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2022       PrintHelp();
2023       exit(0);
2024     } else if (strcmp(arg, "--v8-options") == 0) {
2025       argv[i] = const_cast<char*>("--help");
2026       option_end_index = i+1;
2027     } else if (argv[i][0] != '-') {
2028       option_end_index = i-1;
2029       break;
2030     }
2031   }
2032 }
2033
2034 }  // namespace node
2035
2036
2037 int main(int argc, char *argv[]) {
2038   // Parse a few arguments which are specific to Node.
2039   node::ParseArgs(&argc, argv);
2040   // Parse the rest of the args (up to the 'option_end_index' (where '--' was
2041   // in the command line))
2042   V8::SetFlagsFromCommandLine(&node::option_end_index, argv, false);
2043
2044   // Error out if we don't have a script argument.
2045   if (argc < 2) {
2046     fprintf(stderr, "No script was specified.\n");
2047     node::PrintHelp();
2048     return 1;
2049   }
2050
2051
2052   // Ignore SIGPIPE
2053   struct sigaction sa;
2054   bzero(&sa, sizeof(sa));
2055   sa.sa_handler = SIG_IGN;
2056   sigaction(SIGPIPE, &sa, NULL);
2057
2058
2059   // Initialize the default ev loop.
2060 #ifdef __sun
2061   // TODO(Ryan) I'm experiencing abnormally high load using Solaris's
2062   // EVBACKEND_PORT. Temporarally forcing select() until I debug.
2063   ev_default_loop(EVBACKEND_SELECT);
2064 #else
2065   ev_default_loop(EVFLAG_AUTO);
2066 #endif
2067
2068   ev_prepare_init(&node::next_tick_watcher, node::Tick);
2069   ev_prepare_start(EV_DEFAULT_UC_ &node::next_tick_watcher);
2070   ev_unref(EV_DEFAULT_UC);
2071
2072   ev_idle_init(&node::tick_spinner, node::Spin);
2073
2074   ev_check_init(&node::gc_check, node::Check);
2075   ev_check_start(EV_DEFAULT_UC_ &node::gc_check);
2076   ev_unref(EV_DEFAULT_UC);
2077
2078   ev_idle_init(&node::gc_idle, node::Idle);
2079   ev_timer_init(&node::gc_timer, node::CheckStatus, 5., 5.);
2080
2081
2082   // Setup the EIO thread pool
2083   { // It requires 3, yes 3, watchers.
2084     ev_idle_init(&node::eio_poller, node::DoPoll);
2085
2086     ev_async_init(&node::eio_want_poll_notifier, node::WantPollNotifier);
2087     ev_async_start(EV_DEFAULT_UC_ &node::eio_want_poll_notifier);
2088     ev_unref(EV_DEFAULT_UC);
2089
2090     ev_async_init(&node::eio_done_poll_notifier, node::DonePollNotifier);
2091     ev_async_start(EV_DEFAULT_UC_ &node::eio_done_poll_notifier);
2092     ev_unref(EV_DEFAULT_UC);
2093
2094     eio_init(node::EIOWantPoll, node::EIODonePoll);
2095     // Don't handle more than 10 reqs on each eio_poll(). This is to avoid
2096     // race conditions. See test/mjsunit/test-eio-race.js
2097     eio_set_max_poll_reqs(10);
2098   }
2099
2100   V8::Initialize();
2101   HandleScope handle_scope;
2102
2103   V8::SetFatalErrorHandler(node::OnFatalError);
2104
2105   // If the --debug flag was specified then initialize the debug thread.
2106   if (node::use_debug_agent) {
2107     // Initialize the async watcher for receiving messages from the debug
2108     // thread and marshal it into the main thread. DebugMessageCallback()
2109     // is called from the main thread to execute a random bit of javascript
2110     // - which will give V8 control so it can handle whatever new message
2111     // had been received on the debug thread.
2112     ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
2113     ev_set_priority(&node::debug_watcher, EV_MAXPRI);
2114     // Set the callback DebugMessageDispatch which is called from the debug
2115     // thread.
2116     Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
2117     // Start the async watcher.
2118     ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
2119     // unref it so that we exit the event loop despite it being active.
2120     ev_unref(EV_DEFAULT_UC);
2121
2122     // Start the debug thread and it's associated TCP server on port 5858.
2123     bool r = Debug::EnableAgent("node " NODE_VERSION, node::debug_port);
2124
2125     // Crappy check that everything went well. FIXME
2126     assert(r);
2127     // Print out some information.
2128     printf("debugger listening on port %d\n", node::debug_port);
2129   }
2130
2131   // Create the one and only Context.
2132   Persistent<Context> context = Context::New();
2133   Context::Scope context_scope(context);
2134
2135   // Create all the objects, load modules, do everything.
2136   // so your next reading stop should be node::Load()!
2137   node::Load(argc, argv);
2138
2139   node::Stdio::Flush();
2140
2141 #ifndef NDEBUG
2142   // Clean up.
2143   context.Dispose();
2144   V8::Dispose();
2145 #endif  // NDEBUG
2146   return 0;
2147 }
2148