1 // Copyright Joyent, Inc. and other Node contributors.
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:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
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.
27 #include <node_dtrace.h>
33 #define snprintf _snprintf
37 #if !defined(_MSC_VER)
40 #define strcasecmp _stricmp
42 #include <limits.h> /* PATH_MAX */
44 #if !defined(_MSC_VER)
45 #include <unistd.h> /* setuid, getuid */
49 #define getcwd _getcwd
51 #define getpid _getpid
57 #include <sys/types.h>
59 #if defined(__MINGW32__) || defined(_MSC_VER)
60 # include <platform_win32.h> /* winapi_perror() */
64 # include <dlfcn.h> /* dlopen(), dlsym() */
65 # include <pwd.h> /* getpwnam() */
66 # include <grp.h> /* getgrnam() */
70 #include <node_buffer.h>
72 # include <node_io_watcher.h>
74 #include <node_file.h>
75 #include <node_http_parser.h>
77 # include <node_signal_watcher.h>
78 # include <node_stat_watcher.h>
80 #include <node_constants.h>
81 #include <node_javascript.h>
82 #include <node_version.h>
83 #include <node_string.h>
85 # include <node_crypto.h>
87 #include <node_script.h>
88 #include <v8_typed_array.h>
93 # include <crt_externs.h>
94 # define environ (*_NSGetEnviron())
95 # elif !defined(_MSC_VER)
96 extern char **environ;
101 static Persistent<Object> process;
103 static Persistent<String> errno_symbol;
104 static Persistent<String> syscall_symbol;
105 static Persistent<String> errpath_symbol;
106 static Persistent<String> code_symbol;
108 static Persistent<String> rss_symbol;
109 static Persistent<String> heap_total_symbol;
110 static Persistent<String> heap_used_symbol;
112 static Persistent<String> listeners_symbol;
113 static Persistent<String> uncaught_exception_symbol;
114 static Persistent<String> emit_symbol;
117 static char *eval_string = NULL;
118 static int option_end_index = 0;
119 static bool use_debug_agent = false;
120 static bool debug_wait_connect = false;
121 static int debug_port=5858;
122 static int max_stack_size = 0;
124 static uv_check_t check_tick_watcher;
125 static uv_prepare_t prepare_tick_watcher;
126 static uv_idle_t tick_spinner;
127 static bool need_tick_cb;
128 static Persistent<String> tick_callback_sym;
131 #ifdef OPENSSL_NPN_NEGOTIATED
132 static bool use_npn = true;
134 static bool use_npn = false;
137 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
138 static bool use_sni = true;
140 static bool use_sni = false;
143 // Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
144 // scoped at file-level rather than method-level to avoid excess stack usage.
145 static char getbuf[PATH_MAX + 1];
147 // We need to notify V8 when we're idle so that it can run the garbage
148 // collector. The interface to this is V8::IdleNotification(). It returns
149 // true if the heap hasn't be fully compacted, and needs to be run again.
150 // Returning false means that it doesn't have anymore work to do.
152 // A rather convoluted algorithm has been devised to determine when Node is
153 // idle. You'll have to figure it out for yourself.
154 static uv_check_t gc_check;
155 static uv_idle_t gc_idle;
156 static uv_timer_t gc_timer;
160 #define FAST_TICK 700.
161 #define GC_WAIT_TIME 5000.
162 #define RPM_SAMPLES 100
163 #define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
164 static int64_t tick_times[RPM_SAMPLES];
165 static int tick_time_head;
167 static void CheckStatus(uv_timer_t* watcher, int status);
169 static void StartGCTimer () {
170 if (!uv_is_active((uv_handle_t*) &gc_timer)) {
171 uv_timer_start(&node::gc_timer, node::CheckStatus, 5000, 5000);
175 static void StopGCTimer () {
176 if (uv_is_active((uv_handle_t*) &gc_timer)) {
177 uv_timer_stop(&gc_timer);
181 static void Idle(uv_idle_t* watcher, int status) {
182 assert((uv_idle_t*) watcher == &gc_idle);
184 if (V8::IdleNotification()) {
185 uv_idle_stop(&gc_idle);
191 // Called directly after every call to select() (or epoll, or whatever)
192 static void Check(uv_check_t* watcher, int status) {
193 assert(watcher == &gc_check);
195 tick_times[tick_time_head] = uv_now(uv_default_loop());
196 tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
200 for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
201 double d = TICK_TIME(i+1) - TICK_TIME(i+2);
202 //printf("d = %f\n", d);
203 // If in the last 5 ticks the difference between
204 // ticks was less than 0.7 seconds, then continue.
211 // Otherwise start the gc!
213 //fprintf(stderr, "start idle 2\n");
214 uv_idle_start(&node::gc_idle, node::Idle);
218 static void Tick(void) {
219 // Avoid entering a V8 scope.
220 if (!need_tick_cb) return;
222 need_tick_cb = false;
223 if (uv_is_active((uv_handle_t*) &tick_spinner)) {
224 uv_idle_stop(&tick_spinner);
225 uv_unref(uv_default_loop());
230 if (tick_callback_sym.IsEmpty()) {
231 // Lazily set the symbol
233 Persistent<String>::New(String::NewSymbol("_tickCallback"));
236 Local<Value> cb_v = process->Get(tick_callback_sym);
237 if (!cb_v->IsFunction()) return;
238 Local<Function> cb = Local<Function>::Cast(cb_v);
242 cb->Call(process, 0, NULL);
244 if (try_catch.HasCaught()) {
245 FatalException(try_catch);
250 static void Spin(uv_idle_t* handle, int status) {
251 assert((uv_idle_t*) handle == &tick_spinner);
257 static Handle<Value> NeedTickCallback(const Arguments& args) {
260 // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
261 // sufficent, the problem is only in the case of the very last "tick" -
262 // there is nothing left to do in the event loop and libev will exit. The
263 // ev_prepare callback isn't called before exiting. Thus we start this
264 // tick_spinner to keep the event loop alive long enough to handle it.
265 if (!uv_is_active((uv_handle_t*) &tick_spinner)) {
266 uv_idle_start(&tick_spinner, Spin);
267 uv_ref(uv_default_loop());
273 static void PrepareTick(uv_prepare_t* handle, int status) {
274 assert(handle == &prepare_tick_watcher);
280 static void CheckTick(uv_check_t* handle, int status) {
281 assert(handle == &check_tick_watcher);
286 static inline const char *errno_string(int errorno) {
287 #define ERRNO_CASE(e) case e: return #e;
295 ERRNO_CASE(EADDRINUSE);
299 ERRNO_CASE(EADDRNOTAVAIL);
303 ERRNO_CASE(EAFNOSUPPORT);
311 # if EAGAIN != EWOULDBLOCK
312 ERRNO_CASE(EWOULDBLOCK);
317 ERRNO_CASE(EALREADY);
333 ERRNO_CASE(ECANCELED);
341 ERRNO_CASE(ECONNABORTED);
345 ERRNO_CASE(ECONNREFUSED);
349 ERRNO_CASE(ECONNRESET);
357 ERRNO_CASE(EDESTADDRREQ);
381 ERRNO_CASE(EHOSTUNREACH);
393 ERRNO_CASE(EINPROGRESS);
429 ERRNO_CASE(EMSGSIZE);
433 ERRNO_CASE(EMULTIHOP);
437 ERRNO_CASE(ENAMETOOLONG);
441 ERRNO_CASE(ENETDOWN);
445 ERRNO_CASE(ENETRESET);
449 ERRNO_CASE(ENETUNREACH);
481 # if ENOLINK != ENOLCK
495 ERRNO_CASE(ENOPROTOOPT);
515 ERRNO_CASE(ENOTCONN);
523 ERRNO_CASE(ENOTEMPTY);
527 ERRNO_CASE(ENOTSOCK);
534 ERRNO_CASE(EOPNOTSUPP);
548 ERRNO_CASE(EOVERFLOW);
563 #ifdef EPROTONOSUPPORT
564 ERRNO_CASE(EPROTONOSUPPORT);
568 ERRNO_CASE(EPROTOTYPE);
596 ERRNO_CASE(ETIMEDOUT);
608 ERRNO_CASE(WSAEINTR);
612 ERRNO_CASE(WSAEBADF);
616 ERRNO_CASE(WSAEACCES);
620 ERRNO_CASE(WSAEFAULT);
624 ERRNO_CASE(WSAEINVAL);
628 ERRNO_CASE(WSAEMFILE);
631 #ifdef WSAEWOULDBLOCK
632 ERRNO_CASE(WSAEWOULDBLOCK);
635 #ifdef WSAEINPROGRESS
636 ERRNO_CASE(WSAEINPROGRESS);
640 ERRNO_CASE(WSAEALREADY);
644 ERRNO_CASE(WSAENOTSOCK);
647 #ifdef WSAEDESTADDRREQ
648 ERRNO_CASE(WSAEDESTADDRREQ);
652 ERRNO_CASE(WSAEMSGSIZE);
656 ERRNO_CASE(WSAEPROTOTYPE);
659 #ifdef WSAENOPROTOOPT
660 ERRNO_CASE(WSAENOPROTOOPT);
663 #ifdef WSAEPROTONOSUPPORT
664 ERRNO_CASE(WSAEPROTONOSUPPORT);
667 #ifdef WSAESOCKTNOSUPPORT
668 ERRNO_CASE(WSAESOCKTNOSUPPORT);
672 ERRNO_CASE(WSAEOPNOTSUPP);
675 #ifdef WSAEPFNOSUPPORT
676 ERRNO_CASE(WSAEPFNOSUPPORT);
679 #ifdef WSAEAFNOSUPPORT
680 ERRNO_CASE(WSAEAFNOSUPPORT);
684 ERRNO_CASE(WSAEADDRINUSE);
687 #ifdef WSAEADDRNOTAVAIL
688 ERRNO_CASE(WSAEADDRNOTAVAIL);
692 ERRNO_CASE(WSAENETDOWN);
695 #ifdef WSAENETUNREACH
696 ERRNO_CASE(WSAENETUNREACH);
700 ERRNO_CASE(WSAENETRESET);
703 #ifdef WSAECONNABORTED
704 ERRNO_CASE(WSAECONNABORTED);
708 ERRNO_CASE(WSAECONNRESET);
712 ERRNO_CASE(WSAENOBUFS);
716 ERRNO_CASE(WSAEISCONN);
720 ERRNO_CASE(WSAENOTCONN);
724 ERRNO_CASE(WSAESHUTDOWN);
727 #ifdef WSAETOOMANYREFS
728 ERRNO_CASE(WSAETOOMANYREFS);
732 ERRNO_CASE(WSAETIMEDOUT);
735 #ifdef WSAECONNREFUSED
736 ERRNO_CASE(WSAECONNREFUSED);
740 ERRNO_CASE(WSAELOOP);
743 #ifdef WSAENAMETOOLONG
744 ERRNO_CASE(WSAENAMETOOLONG);
748 ERRNO_CASE(WSAEHOSTDOWN);
751 #ifdef WSAEHOSTUNREACH
752 ERRNO_CASE(WSAEHOSTUNREACH);
756 ERRNO_CASE(WSAENOTEMPTY);
760 ERRNO_CASE(WSAEPROCLIM);
764 ERRNO_CASE(WSAEUSERS);
768 ERRNO_CASE(WSAEDQUOT);
772 ERRNO_CASE(WSAESTALE);
776 ERRNO_CASE(WSAEREMOTE);
779 #ifdef WSASYSNOTREADY
780 ERRNO_CASE(WSASYSNOTREADY);
783 #ifdef WSAVERNOTSUPPORTED
784 ERRNO_CASE(WSAVERNOTSUPPORTED);
787 #ifdef WSANOTINITIALISED
788 ERRNO_CASE(WSANOTINITIALISED);
792 ERRNO_CASE(WSAEDISCON);
796 ERRNO_CASE(WSAENOMORE);
800 ERRNO_CASE(WSAECANCELLED);
803 #ifdef WSAEINVALIDPROCTABLE
804 ERRNO_CASE(WSAEINVALIDPROCTABLE);
807 #ifdef WSAEINVALIDPROVIDER
808 ERRNO_CASE(WSAEINVALIDPROVIDER);
811 #ifdef WSAEPROVIDERFAILEDINIT
812 ERRNO_CASE(WSAEPROVIDERFAILEDINIT);
815 #ifdef WSASYSCALLFAILURE
816 ERRNO_CASE(WSASYSCALLFAILURE);
819 #ifdef WSASERVICE_NOT_FOUND
820 ERRNO_CASE(WSASERVICE_NOT_FOUND);
823 #ifdef WSATYPE_NOT_FOUND
824 ERRNO_CASE(WSATYPE_NOT_FOUND);
828 ERRNO_CASE(WSA_E_NO_MORE);
831 #ifdef WSA_E_CANCELLED
832 ERRNO_CASE(WSA_E_CANCELLED);
839 const char *signo_string(int signo) {
840 #define SIGNO_CASE(e) case e: return #e;
868 # if SIGABRT != SIGIOT
912 SIGNO_CASE(SIGSTKFLT);
949 SIGNO_CASE(SIGVTALRM);
957 SIGNO_CASE(SIGWINCH);
965 # if SIGPOLL != SIGIO
975 # if SIGPWR != SIGLOST
989 Local<Value> ErrnoException(int errorno,
994 Local<String> estring = String::NewSymbol(errno_string(errorno));
997 msg = strerror(errorno);
999 msg = winapi_strerror(errorno);
1002 Local<String> message = String::NewSymbol(msg);
1004 Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
1005 Local<String> cons2 = String::Concat(cons1, message);
1007 if (syscall_symbol.IsEmpty()) {
1008 syscall_symbol = NODE_PSYMBOL("syscall");
1009 errno_symbol = NODE_PSYMBOL("errno");
1010 errpath_symbol = NODE_PSYMBOL("path");
1011 code_symbol = NODE_PSYMBOL("code");
1015 Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
1016 Local<String> cons4 = String::Concat(cons3, String::New(path));
1017 Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
1018 e = Exception::Error(cons5);
1020 e = Exception::Error(cons2);
1023 Local<Object> obj = e->ToObject();
1025 obj->Set(errno_symbol, Integer::New(errorno));
1026 obj->Set(code_symbol, estring);
1027 if (path) obj->Set(errpath_symbol, String::New(path));
1028 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
1033 Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
1034 const Arguments& args) {
1037 const int argc = args.Length();
1038 Local<Value>* argv = new Local<Value>[argc];
1040 for (int i = 0; i < argc; ++i) {
1044 Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
1048 return scope.Close(instance);
1052 // MakeCallback may only be made directly off the event loop.
1053 // That is there can be no JavaScript stack frames underneath it.
1054 // (Is there any way to assert that?)
1056 // Maybe make this a method of a node::Handle super class
1058 void MakeCallback(Handle<Object> object,
1061 Handle<Value> argv[]) {
1064 Local<Value> callback_v = object->Get(String::New(method));
1065 if (!callback_v->IsFunction()) {
1066 fprintf(stderr, "method = %s", method);
1068 assert(callback_v->IsFunction());
1069 Local<Function> callback = Local<Function>::Cast(callback_v);
1071 // TODO Hook for long stack traces to be made here.
1075 callback->Call(object, argc, argv);
1077 if (try_catch.HasCaught()) {
1078 FatalException(try_catch);
1083 void SetErrno(uv_err_t err) {
1086 if (errno_symbol.IsEmpty()) {
1087 errno_symbol = NODE_PSYMBOL("errno");
1090 if (err.code == UV_UNKNOWN) {
1091 char errno_buf[100];
1092 snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
1093 Context::GetCurrent()->Global()->Set(errno_symbol, String::New(errno_buf));
1095 Context::GetCurrent()->Global()->Set(errno_symbol,
1096 String::NewSymbol(uv_err_name(err)));
1101 enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1104 if (!encoding_v->IsString()) return _default;
1106 String::Utf8Value encoding(encoding_v->ToString());
1108 if (strcasecmp(*encoding, "utf8") == 0) {
1110 } else if (strcasecmp(*encoding, "utf-8") == 0) {
1112 } else if (strcasecmp(*encoding, "ascii") == 0) {
1114 } else if (strcasecmp(*encoding, "base64") == 0) {
1116 } else if (strcasecmp(*encoding, "ucs2") == 0) {
1118 } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1120 } else if (strcasecmp(*encoding, "binary") == 0) {
1122 } else if (strcasecmp(*encoding, "hex") == 0) {
1124 } else if (strcasecmp(*encoding, "raw") == 0) {
1125 fprintf(stderr, "'raw' (array of integers) has been removed. "
1128 } else if (strcasecmp(*encoding, "raws") == 0) {
1129 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1130 "Please update your code.\n");
1137 Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1140 if (!len) return scope.Close(String::Empty());
1142 if (encoding == BINARY) {
1143 const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
1144 uint16_t * twobytebuf = new uint16_t[len];
1145 for (size_t i = 0; i < len; i++) {
1146 // XXX is the following line platform independent?
1147 twobytebuf[i] = cbuf[i];
1149 Local<String> chunk = String::New(twobytebuf, len);
1150 delete [] twobytebuf; // TODO use ExternalTwoByteString?
1151 return scope.Close(chunk);
1154 // utf8 or ascii encoding
1155 Local<String> chunk = String::New((const char*)buf, len);
1156 return scope.Close(chunk);
1159 // Returns -1 if the handle was not valid for decoding
1160 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1163 if (val->IsArray()) {
1164 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1170 Local<String> str = val->ToString();
1172 if (encoding == UTF8) return str->Utf8Length();
1173 else if (encoding == UCS2) return str->Length() * 2;
1174 else if (encoding == HEX) return str->Length() / 2;
1176 return str->Length();
1180 # define MIN(a, b) ((a) < (b) ? (a) : (b))
1183 // Returns number of bytes written.
1184 ssize_t DecodeWrite(char *buf,
1186 v8::Handle<v8::Value> val,
1187 enum encoding encoding) {
1191 // A lot of improvement can be made here. See:
1192 // http://code.google.com/p/v8/issues/detail?id=270
1193 // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
1194 // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
1196 if (val->IsArray()) {
1197 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1203 Local<String> str = val->ToString();
1205 if (encoding == UTF8) {
1206 str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
1210 if (encoding == ASCII) {
1211 str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1215 // THIS IS AWFUL!!! FIXME
1217 assert(encoding == BINARY);
1219 uint16_t * twobytebuf = new uint16_t[buflen];
1221 str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1223 for (size_t i = 0; i < buflen; i++) {
1224 unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
1228 delete [] twobytebuf;
1234 void DisplayExceptionLine (TryCatch &try_catch) {
1237 Handle<Message> message = try_catch.Message();
1239 uv_tty_reset_mode();
1241 fprintf(stderr, "\n");
1243 if (!message.IsEmpty()) {
1244 // Print (filename):(line number): (message).
1245 String::Utf8Value filename(message->GetScriptResourceName());
1246 const char* filename_string = *filename;
1247 int linenum = message->GetLineNumber();
1248 fprintf(stderr, "%s:%i\n", filename_string, linenum);
1249 // Print line of source code.
1250 String::Utf8Value sourceline(message->GetSourceLine());
1251 const char* sourceline_string = *sourceline;
1257 // Because of how CommonJS modules work, all scripts are wrapped with a
1258 // "function (function (exports, __filename, ...) {"
1259 // to provide script local variables.
1261 // When reporting errors on the first line of a script, this wrapper
1262 // function is leaked to the user. This HACK is to remove it. The length
1263 // of the wrapper is 62. That wrapper is defined in src/node.js
1265 // If that wrapper is ever changed, then this number also has to be
1266 // updated. Or - someone could clean this up so that the two peices
1267 // don't need to be changed.
1269 // Even better would be to get support into V8 for wrappers that
1270 // shouldn't be reported to users.
1271 int offset = linenum == 1 ? 62 : 0;
1273 fprintf(stderr, "%s\n", sourceline_string + offset);
1274 // Print wavy underline (GetUnderline is deprecated).
1275 int start = message->GetStartColumn();
1276 for (int i = offset; i < start; i++) {
1277 fprintf(stderr, " ");
1279 int end = message->GetEndColumn();
1280 for (int i = start; i < end; i++) {
1281 fprintf(stderr, "^");
1283 fprintf(stderr, "\n");
1288 static void ReportException(TryCatch &try_catch, bool show_line) {
1290 Handle<Message> message = try_catch.Message();
1292 if (show_line) DisplayExceptionLine(try_catch);
1294 String::Utf8Value trace(try_catch.StackTrace());
1296 // range errors have a trace member set to undefined
1297 if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) {
1298 fprintf(stderr, "%s\n", *trace);
1300 // this really only happens for RangeErrors, since they're the only
1301 // kind that won't have all this info in the trace, or when non-Error
1302 // objects are thrown manually.
1303 Local<Value> er = try_catch.Exception();
1304 bool isErrorObject = er->IsObject() &&
1305 !(er->ToObject()->Get(String::New("message"))->IsUndefined()) &&
1306 !(er->ToObject()->Get(String::New("name"))->IsUndefined());
1308 if (isErrorObject) {
1309 String::Utf8Value name(er->ToObject()->Get(String::New("name")));
1310 fprintf(stderr, "%s: ", *name);
1313 String::Utf8Value msg(!isErrorObject ? er->ToString()
1314 : er->ToObject()->Get(String::New("message"))->ToString());
1315 fprintf(stderr, "%s\n", *msg);
1321 // Executes a str within the current v8 context.
1322 Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
1326 Local<v8::Script> script = v8::Script::Compile(source, filename);
1327 if (script.IsEmpty()) {
1328 ReportException(try_catch, true);
1332 Local<Value> result = script->Run();
1333 if (result.IsEmpty()) {
1334 ReportException(try_catch, true);
1338 return scope.Close(result);
1342 static Handle<Value> Chdir(const Arguments& args) {
1345 if (args.Length() != 1 || !args[0]->IsString()) {
1346 return ThrowException(Exception::Error(String::New("Bad argument.")));
1349 String::Utf8Value path(args[0]->ToString());
1351 int r = chdir(*path);
1354 return ThrowException(Exception::Error(String::New(strerror(errno))));
1360 static Handle<Value> Cwd(const Arguments& args) {
1362 assert(args.Length() == 0);
1364 char *r = getcwd(getbuf, ARRAY_SIZE(getbuf) - 1);
1366 return ThrowException(Exception::Error(String::New(strerror(errno))));
1369 getbuf[ARRAY_SIZE(getbuf) - 1] = '\0';
1370 Local<String> cwd = String::New(r);
1372 return scope.Close(cwd);
1375 static Handle<Value> Umask(const Arguments& args) {
1379 if (args.Length() < 1 || args[0]->IsUndefined()) {
1383 } else if(!args[0]->IsInt32() && !args[0]->IsString()) {
1384 return ThrowException(Exception::TypeError(
1385 String::New("argument must be an integer or octal string.")));
1389 if(args[0]->IsInt32()) {
1390 oct = args[0]->Uint32Value();
1393 String::Utf8Value str(args[0]);
1395 // Parse the octal string.
1396 for (int i = 0; i < str.length(); i++) {
1398 if (c > '7' || c < '0') {
1399 return ThrowException(Exception::TypeError(
1400 String::New("invalid octal string")));
1406 old = umask(static_cast<mode_t>(oct));
1409 return scope.Close(Uint32::New(old));
1415 static Handle<Value> GetUid(const Arguments& args) {
1417 assert(args.Length() == 0);
1419 return scope.Close(Integer::New(uid));
1423 static Handle<Value> GetGid(const Arguments& args) {
1425 assert(args.Length() == 0);
1427 return scope.Close(Integer::New(gid));
1431 static Handle<Value> SetGid(const Arguments& args) {
1434 if (args.Length() < 1) {
1435 return ThrowException(Exception::Error(
1436 String::New("setgid requires 1 argument")));
1441 if (args[0]->IsNumber()) {
1442 gid = args[0]->Int32Value();
1443 } else if (args[0]->IsString()) {
1444 String::Utf8Value grpnam(args[0]->ToString());
1445 struct group grp, *grpp = NULL;
1448 if ((err = getgrnam_r(*grpnam, &grp, getbuf, ARRAY_SIZE(getbuf), &grpp)) ||
1451 return ThrowException(Exception::Error(
1452 String::New("setgid group id does not exist")));
1454 return ThrowException(ErrnoException(errno, "getgrnam_r"));
1459 return ThrowException(Exception::Error(
1460 String::New("setgid argument must be a number or a string")));
1464 if ((result = setgid(gid)) != 0) {
1465 return ThrowException(ErrnoException(errno, "setgid"));
1471 static Handle<Value> SetUid(const Arguments& args) {
1474 if (args.Length() < 1) {
1475 return ThrowException(Exception::Error(
1476 String::New("setuid requires 1 argument")));
1481 if (args[0]->IsNumber()) {
1482 uid = args[0]->Int32Value();
1483 } else if (args[0]->IsString()) {
1484 String::Utf8Value pwnam(args[0]->ToString());
1485 struct passwd pwd, *pwdp = NULL;
1488 if ((err = getpwnam_r(*pwnam, &pwd, getbuf, ARRAY_SIZE(getbuf), &pwdp)) ||
1491 return ThrowException(Exception::Error(
1492 String::New("setuid user id does not exist")));
1494 return ThrowException(ErrnoException(errno, "getpwnam_r"));
1499 return ThrowException(Exception::Error(
1500 String::New("setuid argument must be a number or a string")));
1504 if ((result = setuid(uid)) != 0) {
1505 return ThrowException(ErrnoException(errno, "setuid"));
1514 v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
1516 exit(args[0]->IntegerValue());
1521 static void CheckStatus(uv_timer_t* watcher, int status) {
1522 assert(watcher == &gc_timer);
1525 if (!uv_is_active((uv_handle_t*) &gc_idle)) {
1526 HeapStatistics stats;
1527 V8::GetHeapStatistics(&stats);
1528 if (stats.total_heap_size() > 1024 * 1024 * 128) {
1529 // larger than 128 megs, just start the idle watcher
1530 uv_idle_start(&node::gc_idle, node::Idle);
1535 double d = uv_now(uv_default_loop()) - TICK_TIME(3);
1537 //printfb("timer d = %f\n", d);
1539 if (d >= GC_WAIT_TIME - 1.) {
1540 //fprintf(stderr, "start idle\n");
1541 uv_idle_start(&node::gc_idle, node::Idle);
1545 static Handle<Value> Uptime(const Arguments& args) {
1547 assert(args.Length() == 0);
1549 double uptime = Platform::GetUptime(true);
1555 return scope.Close(Number::New(uptime));
1559 v8::Handle<v8::Value> UVCounters(const v8::Arguments& args) {
1562 uv_counters_t* c = &uv_default_loop()->counters;
1564 Local<Object> obj = Object::New();
1566 #define setc(name) obj->Set(String::New(#name), Integer::New(c->name));
1586 return scope.Close(obj);
1590 v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1592 assert(args.Length() == 0);
1596 int r = Platform::GetMemory(&rss);
1599 return ThrowException(Exception::Error(String::New(strerror(errno))));
1602 Local<Object> info = Object::New();
1604 if (rss_symbol.IsEmpty()) {
1605 rss_symbol = NODE_PSYMBOL("rss");
1606 heap_total_symbol = NODE_PSYMBOL("heapTotal");
1607 heap_used_symbol = NODE_PSYMBOL("heapUsed");
1610 info->Set(rss_symbol, Integer::NewFromUnsigned(rss));
1613 HeapStatistics v8_heap_stats;
1614 V8::GetHeapStatistics(&v8_heap_stats);
1615 info->Set(heap_total_symbol,
1616 Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
1617 info->Set(heap_used_symbol,
1618 Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1620 return scope.Close(info);
1626 Handle<Value> Kill(const Arguments& args) {
1629 if (args.Length() != 2) {
1630 return ThrowException(Exception::Error(String::New("Bad argument.")));
1633 pid_t pid = args[0]->IntegerValue();
1634 int sig = args[1]->Int32Value();
1635 int r = kill(pid, sig);
1637 if (r != 0) return ThrowException(ErrnoException(errno, "kill"));
1643 typedef void (*extInit)(Handle<Object> exports);
1645 // DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1647 Handle<Value> DLOpen(const v8::Arguments& args) {
1648 node_module_struct compat_mod;
1651 if (args.Length() < 2) return Undefined();
1653 String::Utf8Value filename(args[0]->ToString()); // Cast
1654 Local<Object> target = args[1]->ToObject(); // Cast
1656 // Actually call dlopen().
1657 // FIXME: This is a blocking function and should be called asynchronously!
1658 // This function should be moved to file.cc and use libeio to make this
1660 void *handle = dlopen(*filename, RTLD_LAZY);
1663 if (handle == NULL) {
1664 Local<Value> exception = Exception::Error(String::New(dlerror()));
1665 return ThrowException(exception);
1668 String::Utf8Value symbol(args[0]->ToString());
1669 char *symstr = NULL;
1671 char *sym = *symbol;
1672 char *p = strrchr(sym, '/');
1677 p = strrchr(sym, '.');
1682 size_t slen = strlen(sym);
1683 symstr = static_cast<char*>(calloc(1, slen + sizeof("_module") + 1));
1684 memcpy(symstr, sym, slen);
1685 memcpy(symstr+slen, "_module", sizeof("_module") + 1);
1688 // Get the init() function from the dynamically shared object.
1689 node_module_struct *mod = static_cast<node_module_struct *>(dlsym(handle, symstr));
1693 // Error out if not found.
1695 /* Start Compatibility hack: Remove once everyone is using NODE_MODULE macro */
1696 memset(&compat_mod, 0, sizeof compat_mod);
1699 mod->version = NODE_MODULE_VERSION;
1701 void *init_handle = dlsym(handle, "init");
1702 if (init_handle == NULL) {
1704 Local<Value> exception =
1705 Exception::Error(String::New("No module symbol found in module."));
1706 return ThrowException(exception);
1708 mod->register_func = (extInit)(init_handle);
1709 /* End Compatibility hack */
1712 if (mod->version != NODE_MODULE_VERSION) {
1713 Local<Value> exception =
1714 Exception::Error(String::New("Module version mismatch, refusing to load."));
1715 return ThrowException(exception);
1718 // Execute the C++ module
1719 mod->register_func(target);
1721 // Tell coverity that 'handle' should not be freed when we return.
1722 // coverity[leaked_storage]
1729 // TODO remove me before 0.4
1730 Handle<Value> Compile(const Arguments& args) {
1734 if (args.Length() < 2) {
1735 return ThrowException(Exception::TypeError(
1736 String::New("needs two arguments.")));
1739 static bool shown_error_message = false;
1741 if (!shown_error_message) {
1742 shown_error_message = true;
1743 fprintf(stderr, "(node) process.compile should not be used. "
1744 "Use require('vm').runInThisContext instead.\n");
1747 Local<String> source = args[0]->ToString();
1748 Local<String> filename = args[1]->ToString();
1752 Local<v8::Script> script = v8::Script::Compile(source, filename);
1753 if (try_catch.HasCaught()) {
1754 // Hack because I can't get a proper stacktrace on SyntaxError
1755 ReportException(try_catch, true);
1759 Local<Value> result = script->Run();
1760 if (try_catch.HasCaught()) {
1761 ReportException(try_catch, false);
1765 return scope.Close(result);
1768 static void OnFatalError(const char* location, const char* message) {
1770 fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1772 fprintf(stderr, "FATAL ERROR: %s\n", message);
1777 static int uncaught_exception_counter = 0;
1779 void FatalException(TryCatch &try_catch) {
1782 // Check if uncaught_exception_counter indicates a recursion
1783 if (uncaught_exception_counter > 0) {
1784 ReportException(try_catch, true);
1788 if (listeners_symbol.IsEmpty()) {
1789 listeners_symbol = NODE_PSYMBOL("listeners");
1790 uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1791 emit_symbol = NODE_PSYMBOL("emit");
1794 Local<Value> listeners_v = process->Get(listeners_symbol);
1795 assert(listeners_v->IsFunction());
1797 Local<Function> listeners = Local<Function>::Cast(listeners_v);
1799 Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1800 Local<Value> argv[1] = { uncaught_exception_symbol_l };
1801 Local<Value> ret = listeners->Call(process, 1, argv);
1803 assert(ret->IsArray());
1805 Local<Array> listener_array = Local<Array>::Cast(ret);
1807 uint32_t length = listener_array->Length();
1808 // Report and exit if process has no "uncaughtException" listener
1810 ReportException(try_catch, true);
1814 // Otherwise fire the process "uncaughtException" event
1815 Local<Value> emit_v = process->Get(emit_symbol);
1816 assert(emit_v->IsFunction());
1818 Local<Function> emit = Local<Function>::Cast(emit_v);
1820 Local<Value> error = try_catch.Exception();
1821 Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
1823 uncaught_exception_counter++;
1824 emit->Call(process, 2, event_argv);
1825 // Decrement so we know if the next exception is a recursion or not
1826 uncaught_exception_counter--;
1830 static uv_async_t debug_watcher;
1832 static void DebugMessageCallback(uv_async_t* watcher, int status) {
1834 assert(watcher == &debug_watcher);
1835 Debug::ProcessDebugMessages();
1838 static void DebugMessageDispatch(void) {
1839 // This function is called from V8's debug thread when a debug TCP client
1840 // has sent a message.
1842 // Send a signal to our main thread saying that it should enter V8 to
1843 // handle the message.
1844 uv_async_send(&debug_watcher);
1847 static void DebugBreakMessageHandler(const Debug::Message& message) {
1848 // do nothing with debug messages.
1849 // The message handler will get changed by DebuggerAgent::CreateSession in
1850 // debug-agent.cc of v8/src when a new session is created
1854 Persistent<Object> binding_cache;
1855 Persistent<Array> module_load_list;
1857 static Handle<Value> Binding(const Arguments& args) {
1860 Local<String> module = args[0]->ToString();
1861 String::Utf8Value module_v(module);
1862 node_module_struct* modp;
1864 if (binding_cache.IsEmpty()) {
1865 binding_cache = Persistent<Object>::New(Object::New());
1868 Local<Object> exports;
1870 if (binding_cache->Has(module)) {
1871 exports = binding_cache->Get(module)->ToObject();
1872 return scope.Close(exports);
1875 // Append a string to process.moduleLoadList
1877 snprintf(buf, 1024, "Binding %s", *module_v);
1878 uint32_t l = module_load_list->Length();
1879 module_load_list->Set(l, String::New(buf));
1881 if ((modp = get_builtin_module(*module_v)) != NULL) {
1882 exports = Object::New();
1883 modp->register_func(exports);
1884 binding_cache->Set(module, exports);
1886 } else if (!strcmp(*module_v, "constants")) {
1887 exports = Object::New();
1888 DefineConstants(exports);
1889 binding_cache->Set(module, exports);
1892 } else if (!strcmp(*module_v, "io_watcher")) {
1893 exports = Object::New();
1894 IOWatcher::Initialize(exports);
1895 binding_cache->Set(module, exports);
1898 } else if (!strcmp(*module_v, "natives")) {
1899 exports = Object::New();
1900 DefineJavaScript(exports);
1901 binding_cache->Set(module, exports);
1905 return ThrowException(Exception::Error(String::New("No such module")));
1908 return scope.Close(exports);
1912 static Handle<Value> ProcessTitleGetter(Local<String> property,
1913 const AccessorInfo& info) {
1916 const char *s = Platform::GetProcessTitle(&len);
1917 return scope.Close(s ? String::New(s, len) : String::Empty());
1921 static void ProcessTitleSetter(Local<String> property,
1923 const AccessorInfo& info) {
1925 String::Utf8Value title(value->ToString());
1926 Platform::SetProcessTitle(*title);
1930 static Handle<Value> EnvGetter(Local<String> property,
1931 const AccessorInfo& info) {
1932 String::Utf8Value key(property);
1933 const char* val = getenv(*key);
1936 return scope.Close(String::New(val));
1942 static Handle<Value> EnvSetter(Local<String> property,
1944 const AccessorInfo& info) {
1946 String::Utf8Value key(property);
1947 String::Utf8Value val(value);
1950 setenv(*key, *val, 1);
1952 int n = key.length() + val.length() + 2;
1953 char* pair = new char[n];
1954 snprintf(pair, n, "%s=%s", *key, *val);
1955 int r = _putenv(pair);
1957 fprintf(stderr, "error putenv: '%s'\n", pair);
1966 static Handle<Integer> EnvQuery(Local<String> property,
1967 const AccessorInfo& info) {
1968 String::Utf8Value key(property);
1971 return scope.Close(Integer::New(None));
1973 return Handle<Integer>();
1977 static Handle<Boolean> EnvDeleter(Local<String> property,
1978 const AccessorInfo& info) {
1981 String::Utf8Value key(property);
1985 unsetenv(*key); // prototyped as `void unsetenv(const char*)` on some platforms
1987 int n = key.length() + 2;
1988 char* pair = new char[n];
1989 snprintf(pair, n, "%s=", *key);
1990 int r = _putenv(pair);
1992 fprintf(stderr, "error unsetenv: '%s'\n", pair);
2003 static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
2007 while (environ[size]) size++;
2009 Local<Array> env = Array::New(size);
2011 for (int i = 0; i < size; ++i) {
2012 const char* var = environ[i];
2013 const char* s = strchr(var, '=');
2014 const int length = s ? s - var : strlen(var);
2015 env->Set(i, String::New(var, length));
2018 return scope.Close(env);
2022 static Handle<Object> GetFeatures() {
2025 Local<Object> obj = Object::New();
2026 obj->Set(String::NewSymbol("debug"),
2027 #if defined(DEBUG) && DEBUG
2034 obj->Set(String::NewSymbol("uv"), True());
2035 obj->Set(String::NewSymbol("ipv6"), True()); // TODO ping libuv
2036 obj->Set(String::NewSymbol("tls_npn"), Boolean::New(use_npn));
2037 obj->Set(String::NewSymbol("tls_sni"), Boolean::New(use_sni));
2038 obj->Set(String::NewSymbol("tls"),
2039 Boolean::New(get_builtin_module("crypto") != NULL));
2041 return scope.Close(obj);
2045 Handle<Object> SetupProcessObject(int argc, char *argv[]) {
2050 Local<FunctionTemplate> process_template = FunctionTemplate::New();
2052 process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
2055 process->SetAccessor(String::New("title"),
2057 ProcessTitleSetter);
2060 process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
2063 // process.installPrefix
2064 process->Set(String::NewSymbol("installPrefix"), String::New(NODE_PREFIX));
2067 // process.moduleLoadList
2068 module_load_list = Persistent<Array>::New(Array::New());
2069 process->Set(String::NewSymbol("moduleLoadList"), module_load_list);
2071 Local<Object> versions = Object::New();
2073 process->Set(String::NewSymbol("versions"), versions);
2074 // +1 to get rid of the leading 'v'
2075 versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
2076 versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
2077 versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
2078 snprintf(buf, 20, "%d.%d", UV_VERSION_MAJOR, UV_VERSION_MINOR);
2079 versions->Set(String::NewSymbol("uv"), String::New(buf));
2081 // Stupid code to slice out the version string.
2082 int c, l = strlen(OPENSSL_VERSION_TEXT);
2083 for (i = j = 0; i < l; i++) {
2084 c = OPENSSL_VERSION_TEXT[i];
2085 if ('0' <= c && c <= '9') {
2086 for (j = i + 1; j < l; j++) {
2087 c = OPENSSL_VERSION_TEXT[j];
2088 if (c == ' ') break;
2093 versions->Set(String::NewSymbol("openssl"),
2094 String::New(OPENSSL_VERSION_TEXT + i, j - i));
2100 process->Set(String::NewSymbol("arch"), String::New(ARCH));
2103 process->Set(String::NewSymbol("platform"), String::New(PLATFORM));
2106 Local<Array> arguments = Array::New(argc - option_end_index + 1);
2107 arguments->Set(Integer::New(0), String::New(argv[0]));
2108 for (j = 1, i = option_end_index; i < argc; j++, i++) {
2109 Local<String> arg = String::New(argv[i]);
2110 arguments->Set(Integer::New(j), arg);
2113 process->Set(String::NewSymbol("argv"), arguments);
2115 // create process.env
2116 Local<ObjectTemplate> envTemplate = ObjectTemplate::New();
2117 envTemplate->SetNamedPropertyHandler(EnvGetter,
2123 Local<Object> env = envTemplate->NewInstance();
2124 process->Set(String::NewSymbol("env"), env);
2126 process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
2127 process->Set(String::NewSymbol("features"), GetFeatures());
2131 process->Set(String::NewSymbol("_eval"), String::New(eval_string));
2134 size_t size = 2*PATH_MAX;
2135 char* execPath = new char[size];
2136 if (uv_exepath(execPath, &size) != 0) {
2137 // as a last ditch effort, fallback on argv[0] ?
2138 process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
2140 process->Set(String::NewSymbol("execPath"), String::New(execPath, size));
2145 // define various internal methods
2146 NODE_SET_METHOD(process, "compile", Compile);
2147 NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
2148 NODE_SET_METHOD(process, "reallyExit", Exit);
2149 NODE_SET_METHOD(process, "chdir", Chdir);
2150 NODE_SET_METHOD(process, "cwd", Cwd);
2152 NODE_SET_METHOD(process, "umask", Umask);
2155 NODE_SET_METHOD(process, "getuid", GetUid);
2156 NODE_SET_METHOD(process, "setuid", SetUid);
2158 NODE_SET_METHOD(process, "setgid", SetGid);
2159 NODE_SET_METHOD(process, "getgid", GetGid);
2161 NODE_SET_METHOD(process, "dlopen", DLOpen);
2162 NODE_SET_METHOD(process, "_kill", Kill);
2165 NODE_SET_METHOD(process, "uptime", Uptime);
2166 NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2167 NODE_SET_METHOD(process, "uvCounters", UVCounters);
2169 NODE_SET_METHOD(process, "binding", Binding);
2175 static void AtExit() {
2176 uv_tty_reset_mode();
2180 static void SignalExit(int signal) {
2181 uv_tty_reset_mode();
2186 void Load(Handle<Object> process) {
2187 // Compile, execute the src/node.js file. (Which was included as static C
2188 // string in node_natives.h. 'natve_node' is the string containing that
2191 // The node.js file returns a function 'f'
2197 Local<Value> f_value = ExecuteString(MainSource(),
2198 IMMUTABLE_STRING("node.js"));
2199 if (try_catch.HasCaught()) {
2200 ReportException(try_catch, true);
2203 assert(f_value->IsFunction());
2204 Local<Function> f = Local<Function>::Cast(f_value);
2206 // Now we call 'f' with the 'process' variable that we've built up with
2207 // all our bindings. Inside node.js we'll take care of assigning things to
2210 // We start the process this way in order to be more modular. Developers
2211 // who do not like how 'src/node.js' setups the module system but do like
2212 // Node's I/O bindings may want to replace 'f' with their own function.
2214 // Add a reference to the global object
2215 Local<Object> global = v8::Context::GetCurrent()->Global();
2216 Local<Value> args[1] = { Local<Value>::New(process) };
2222 f->Call(global, 1, args);
2224 if (try_catch.HasCaught()) {
2225 ReportException(try_catch, true);
2230 static void PrintHelp();
2232 static void ParseDebugOpt(const char* arg) {
2235 use_debug_agent = true;
2236 if (!strcmp (arg, "--debug-brk")) {
2237 debug_wait_connect = true;
2239 } else if (!strcmp(arg, "--debug")) {
2241 } else if (strstr(arg, "--debug-brk=") == arg) {
2242 debug_wait_connect = true;
2243 p = 1 + strchr(arg, '=');
2244 debug_port = atoi(p);
2245 } else if (strstr(arg, "--debug=") == arg) {
2246 p = 1 + strchr(arg, '=');
2247 debug_port = atoi(p);
2249 if (p && debug_port > 1024 && debug_port < 65536)
2252 fprintf(stderr, "Bad debug option.\n");
2253 if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2259 static void PrintHelp() {
2260 printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
2261 " node debug script.js [arguments] \n"
2262 " node cluster script.js [arguments] \n"
2265 " -v, --version print node's version\n"
2266 " -e, --eval script evaluate script\n"
2267 " --v8-options print v8 command line options\n"
2268 " --vars print various compiled-in variables\n"
2269 " --max-stack-size=val set max v8 stack size (bytes)\n"
2271 "Enviromental variables:\n"
2272 "NODE_PATH ':'-separated list of directories\n"
2273 " prefixed to the module search path.\n"
2274 "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
2275 " global contexts.\n"
2276 "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
2278 "Documentation can be found at http://nodejs.org/\n");
2281 // Parse node command line arguments.
2282 static void ParseArgs(int argc, char **argv) {
2285 // TODO use parse opts
2286 for (i = 1; i < argc; i++) {
2287 const char *arg = argv[i];
2288 if (strstr(arg, "--debug") == arg) {
2290 argv[i] = const_cast<char*>("");
2291 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2292 printf("%s\n", NODE_VERSION);
2294 } else if (strcmp(arg, "--vars") == 0) {
2296 printf("NODE_PREFIX: %s\n", NODE_PREFIX);
2299 printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
2302 } else if (strstr(arg, "--max-stack-size=") == arg) {
2304 p = 1 + strchr(arg, '=');
2305 max_stack_size = atoi(p);
2306 argv[i] = const_cast<char*>("");
2307 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2310 } else if (strcmp(arg, "--eval") == 0 || strcmp(arg, "-e") == 0) {
2311 if (argc <= i + 1) {
2312 fprintf(stderr, "Error: --eval requires an argument\n");
2315 argv[i] = const_cast<char*>("");
2316 eval_string = argv[++i];
2317 } else if (strcmp(arg, "--v8-options") == 0) {
2318 argv[i] = const_cast<char*>("--help");
2319 } else if (argv[i][0] != '-') {
2324 option_end_index = i;
2327 static volatile bool debugger_running = false;
2329 static void EnableDebug(bool wait_connect) {
2330 // Start the debug thread and it's associated TCP server on port 5858.
2331 bool r = Debug::EnableAgent("node " NODE_VERSION, debug_port);
2334 // Set up an empty handler so v8 will not continue until a debugger
2335 // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
2336 // except we don't break at the beginning of the script.
2337 // see Debugger::StartAgent in debug.cc of v8/src
2338 Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
2341 // Crappy check that everything went well. FIXME
2344 // Print out some information.
2345 fprintf(stderr, "debugger listening on port %d\n", debug_port);
2347 debugger_running = true;
2352 static void EnableDebugSignalHandler(int signal) {
2353 // Break once process will return execution to v8
2354 v8::Debug::DebugBreak();
2356 if (!debugger_running) {
2357 fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2363 #if defined(__MINGW32__) || defined(_MSC_VER)
2364 static bool EnableDebugSignalHandler(DWORD signal) {
2365 if (signal == CTRL_C_EVENT) exit(1);
2366 if (signal != CTRL_BREAK_EVENT) return false;
2368 // Break once process will return execution to v8
2369 v8::Debug::DebugBreak();
2371 if (!debugger_running) {
2372 fprintf(stderr, "Hit Ctrl+Break - starting debugger agent.\n");
2376 // Run default system action (terminate)
2386 static int RegisterSignalHandler(int signal, void (*handler)(int)) {
2387 struct sigaction sa;
2389 memset(&sa, 0, sizeof(sa));
2390 sa.sa_handler = handler;
2391 sigfillset(&sa.sa_mask);
2392 return sigaction(signal, &sa, NULL);
2397 char** Init(int argc, char *argv[]) {
2398 // Hack aroung with the argv pointer. Used for process.title = "blah".
2399 argv = node::Platform::SetupArgs(argc, argv);
2401 // Parse a few arguments which are specific to Node.
2402 node::ParseArgs(argc, argv);
2403 // Parse the rest of the args (up to the 'option_end_index' (where '--' was
2404 // in the command line))
2405 int v8argc = node::option_end_index;
2406 char **v8argv = argv;
2408 if (node::debug_wait_connect) {
2409 // v8argv is a copy of argv up to the script file argument +2 if --debug-brk
2410 // to expose the v8 debugger js object so that node.js can set
2411 // a breakpoint on the first line of the startup script
2413 v8argv = new char*[v8argc];
2414 memcpy(v8argv, argv, sizeof(argv) * node::option_end_index);
2415 v8argv[node::option_end_index] = const_cast<char*>("--expose_debug_as");
2416 v8argv[node::option_end_index + 1] = const_cast<char*>("v8debug");
2419 // For the normal stack which moves from high to low addresses when frames
2420 // are pushed, we can compute the limit as stack_size bytes below the
2421 // the address of a stack variable (e.g. &stack_var) as an approximation
2422 // of the start of the stack (we're assuming that we haven't pushed a lot
2424 if (node::max_stack_size != 0) {
2426 ResourceConstraints constraints;
2428 uint32_t *stack_limit = &stack_var - (node::max_stack_size / sizeof(uint32_t));
2429 constraints.set_stack_limit(stack_limit);
2430 SetResourceConstraints(&constraints); // Must be done before V8::Initialize
2432 V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
2436 RegisterSignalHandler(SIGPIPE, SIG_IGN);
2437 RegisterSignalHandler(SIGINT, SignalExit);
2438 RegisterSignalHandler(SIGTERM, SignalExit);
2441 uv_prepare_init(uv_default_loop(), &node::prepare_tick_watcher);
2442 uv_prepare_start(&node::prepare_tick_watcher, PrepareTick);
2443 uv_unref(uv_default_loop());
2445 uv_check_init(uv_default_loop(), &node::check_tick_watcher);
2446 uv_check_start(&node::check_tick_watcher, node::CheckTick);
2447 uv_unref(uv_default_loop());
2449 uv_idle_init(uv_default_loop(), &node::tick_spinner);
2450 uv_unref(uv_default_loop());
2452 uv_check_init(uv_default_loop(), &node::gc_check);
2453 uv_check_start(&node::gc_check, node::Check);
2454 uv_unref(uv_default_loop());
2456 uv_idle_init(uv_default_loop(), &node::gc_idle);
2457 uv_unref(uv_default_loop());
2459 uv_timer_init(uv_default_loop(), &node::gc_timer);
2460 uv_unref(uv_default_loop());
2462 V8::SetFatalErrorHandler(node::OnFatalError);
2465 // Set the callback DebugMessageDispatch which is called from the debug
2467 Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
2468 // Initialize the async watcher. DebugMessageCallback() is called from the
2469 // main thread to execute a random bit of javascript - which will give V8
2470 // control so it can handle whatever new message had been received on the
2472 uv_async_init(uv_default_loop(), &node::debug_watcher,
2473 node::DebugMessageCallback);
2474 // unref it so that we exit the event loop despite it being active.
2475 uv_unref(uv_default_loop());
2478 // If the --debug flag was specified then initialize the debug thread.
2479 if (node::use_debug_agent) {
2480 EnableDebug(debug_wait_connect);
2483 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2485 #if defined(__MINGW32__) || defined(_MSC_VER)
2486 SetConsoleCtrlHandler((PHANDLER_ROUTINE) EnableDebugSignalHandler, TRUE);
2494 void EmitExit(v8::Handle<v8::Object> process) {
2495 // process.emit('exit')
2496 Local<Value> emit_v = process->Get(String::New("emit"));
2497 assert(emit_v->IsFunction());
2498 Local<Function> emit = Local<Function>::Cast(emit_v);
2499 Local<Value> args[] = { String::New("exit") };
2501 emit->Call(process, 1, args);
2502 if (try_catch.HasCaught()) {
2503 FatalException(try_catch);
2508 int Start(int argc, char *argv[]) {
2509 // This needs to run *before* V8::Initialize()
2510 argv = Init(argc, argv);
2512 v8::V8::Initialize();
2513 v8::HandleScope handle_scope;
2515 // Create the one and only Context.
2516 Persistent<v8::Context> context = v8::Context::New();
2517 v8::Context::Scope context_scope(context);
2519 Handle<Object> process = SetupProcessObject(argc, argv);
2520 v8_typed_array::AttachBindings(context->Global());
2522 // Create all the objects, load modules, do everything.
2523 // so your next reading stop should be node::Load()!
2526 // All our arguments are loaded. We've evaluated all of the scripts. We
2527 // might even have created TCP servers. Now we enter the main eventloop. If
2528 // there are no watchers on the loop (except for the ones that were
2529 // uv_unref'd) then this function exits. As long as there are active
2530 // watchers, it blocks.
2531 uv_run(uv_default_loop());