blob: 50081c059ad9c705bd2ede0d3a35d101ab12fb07 [file] [log] [blame]
Ryan Dahl55048cd2011-03-10 08:54:521// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
Bert Beldere0f47be2011-01-17 23:22:3621
Ben Noordhuisff4a9d32012-03-09 23:11:1122#include "node.h"
Ben Noordhuis02cab972013-07-31 21:16:0823#include "node_buffer.h"
24#include "node_constants.h"
25#include "node_file.h"
26#include "node_http_parser.h"
27#include "node_javascript.h"
Ben Noordhuis02cab972013-07-31 21:16:0828#include "node_version.h"
Fedor Indutny50839a02014-10-10 22:17:0329#include "node_v8_platform.h"
Ben Noordhuis02cab972013-07-31 21:16:0830
31#if defined HAVE_PERFCTR
32#include "node_counters.h"
33#endif
34
35#if HAVE_OPENSSL
36#include "node_crypto.h"
37#endif
38
Steven R. Loomisac2857b2014-09-05 05:03:2439#if defined(NODE_HAVE_I18N_SUPPORT)
40#include "node_i18n.h"
41#endif
42
Ben Noordhuisc4def502013-10-28 19:18:5943#if defined HAVE_DTRACE || defined HAVE_ETW
Ben Noordhuis02cab972013-07-31 21:16:0844#include "node_dtrace.h"
45#endif
46
Bert Belder22d03c92012-08-06 23:48:1547#include "ares.h"
Trevor Norrisefa62fd2013-09-24 21:12:1148#include "async-wrap.h"
49#include "async-wrap-inl.h"
Ben Noordhuis756b6222013-08-10 22:26:1150#include "env.h"
51#include "env-inl.h"
Ben Noordhuis02cab972013-07-31 21:16:0852#include "handle_wrap.h"
53#include "req_wrap.h"
54#include "string_bytes.h"
Timothy J Fontaine1a09da62014-06-10 23:36:0455#include "util.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1156#include "uv.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1157#include "v8-debug.h"
Ben Noordhuis57231d52013-10-02 04:37:4458#include "v8-profiler.h"
Ben Noordhuis02cab972013-07-31 21:16:0859#include "zlib.h"
Ryan Dahl4635ed72010-03-11 20:40:1960
Ben Noordhuis02cab972013-07-31 21:16:0861#include <assert.h>
62#include <errno.h>
63#include <limits.h> // PATH_MAX
Bert Beldere0f47be2011-01-17 23:22:3664#include <locale.h>
Bert Belder9cec08e2011-05-23 23:42:2265#include <signal.h>
Ryan19478ed2009-03-03 00:56:1566#include <stdio.h>
Ryan34a6f102009-05-28 12:47:1667#include <stdlib.h>
Ryan Dahlc90e44e2010-05-10 23:38:4768#include <string.h>
Ben Noordhuis02cab972013-07-31 21:16:0869#include <sys/types.h>
70
71#if defined(_MSC_VER)
Peter Bright13d6a1f2011-08-06 04:23:2572#include <direct.h>
Peter Brightb9d77772011-08-11 01:45:5673#include <io.h>
Ben Noordhuis02cab972013-07-31 21:16:0874#include <process.h>
Ben Noordhuis02cab972013-07-31 21:16:0875#define strcasecmp _stricmp
76#define getpid _getpid
Peter Brightb9d77772011-08-11 01:45:5677#define umask _umask
78typedef int mode_t;
Ben Noordhuis02cab972013-07-31 21:16:0879#else
Ben Noordhuis68200542013-10-02 10:17:5780#include <sys/resource.h> // getrlimit, setrlimit
Ben Noordhuis02cab972013-07-31 21:16:0881#include <unistd.h> // setuid, getuid
Peter Bright13d6a1f2011-08-06 04:23:2582#endif
Ryane02b71e2009-03-03 23:31:3783
Linus Mårtensson5e4e8ec2013-05-08 12:10:0784#if defined(__POSIX__) && !defined(__ANDROID__)
Ben Noordhuis02cab972013-07-31 21:16:0885#include <pwd.h> // getpwnam()
86#include <grp.h> // getgrnam()
Bert Beldera177d602010-11-25 00:02:5587#endif
88
Fedor Indutny8e29ce92013-07-31 18:07:2989#ifdef __APPLE__
Ben Noordhuis02cab972013-07-31 21:16:0890#include <crt_externs.h>
91#define environ (*_NSGetEnviron())
Fedor Indutny8e29ce92013-07-31 18:07:2992#elif !defined(_MSC_VER)
Ryan3e4fc9f2009-09-10 14:48:3893extern char **environ;
Fedor Indutny8e29ce92013-07-31 18:07:2994#endif
Ryan3e4fc9f2009-09-10 14:48:3895
Ryand6c9d312009-09-11 14:02:2996namespace node {
97
Ben Noordhuis110a9cd2013-07-03 02:23:4498using v8::Array;
Ben Noordhuis0693d222013-06-29 06:16:2599using v8::ArrayBuffer;
Ben Noordhuis110a9cd2013-07-03 02:23:44100using v8::Boolean;
101using v8::Context;
Fedor Indutnyce04c722014-03-13 16:38:14102using v8::EscapableHandleScope;
Ben Noordhuis110a9cd2013-07-03 02:23:44103using v8::Exception;
104using v8::Function;
105using v8::FunctionCallbackInfo;
106using v8::FunctionTemplate;
Ben Noordhuis511af4d2013-07-30 19:28:43107using v8::Handle;
Ben Noordhuis110a9cd2013-07-03 02:23:44108using v8::HandleScope;
109using v8::HeapStatistics;
110using v8::Integer;
111using v8::Isolate;
Ben Noordhuis511af4d2013-07-30 19:28:43112using v8::Local;
Ben Noordhuis110a9cd2013-07-03 02:23:44113using v8::Locker;
114using v8::Message;
115using v8::Number;
116using v8::Object;
117using v8::ObjectTemplate;
Ben Noordhuis110a9cd2013-07-03 02:23:44118using v8::PropertyCallbackInfo;
Ben Noordhuis511af4d2013-07-30 19:28:43119using v8::String;
Ben Noordhuis110a9cd2013-07-03 02:23:44120using v8::TryCatch;
121using v8::Uint32;
122using v8::V8;
123using v8::Value;
Trevor Norrisbdc2ea42014-10-08 08:34:46124using v8::kExternalUint32Array;
Ben Noordhuis110a9cd2013-07-03 02:23:44125
Ben Noordhuis74a82152012-02-03 15:32:00126static bool print_eval = false;
Nathan Rajlichfeaa8a42012-03-21 07:05:25127static bool force_repl = false;
isaacs5b399292012-06-21 18:42:33128static bool trace_deprecation = false;
isaacs5038f402013-03-06 01:46:37129static bool throw_deprecation = false;
Ben Noordhuis185c5152013-09-02 14:42:01130static const char* eval_string = NULL;
Ben Noordhuis74a82152012-02-03 15:32:00131static bool use_debug_agent = false;
132static bool debug_wait_connect = false;
Fedor Indutny8e29ce92013-07-31 18:07:29133static int debug_port = 5858;
Ben Noordhuis9566fe82013-10-03 08:45:32134static bool v8_is_profiling = false;
Keith M Wesolowski76b98462013-12-17 00:00:44135static node_module* modpending;
136static node_module* modlist_builtin;
137static node_module* modlist_addon;
Ben Noordhuis74a82152012-02-03 15:32:00138
Steven R. Loomisac2857b2014-09-05 05:03:24139#if defined(NODE_HAVE_I18N_SUPPORT)
140// Path to ICU data (for i18n / Intl)
141static const char* icu_data_dir = NULL;
142#endif
143
isaacs48c3d202012-06-21 19:20:23144// used by C++ modules as well
145bool no_deprecation = false;
146
Ben Noordhuis74a82152012-02-03 15:32:00147// process-relative uptime base, initialized at start-up
148static double prog_start_time;
Ben Noordhuisca363cf2013-10-15 21:32:18149static bool debugger_running;
Ben Noordhuis5d0816b2013-01-06 22:06:48150static uv_async_t dispatch_debug_messages_async;
151
Fedor Indutny75adde02014-02-21 13:02:42152static Isolate* node_isolate = NULL;
Ben Noordhuis5d0816b2013-01-06 22:06:48153
Felix Geisendörfer0da4c672014-01-20 08:47:19154int WRITE_UTF8_FLAGS = v8::String::HINT_MANY_WRITES_EXPECTED |
155 v8::String::NO_NULL_TERMINATION;
Ryan Dahlf80cc692010-01-06 09:17:58156
Ben Noordhuis0693d222013-06-29 06:16:25157class ArrayBufferAllocator : public ArrayBuffer::Allocator {
Fedor Indutny8e29ce92013-07-31 18:07:29158 public:
Ben Noordhuis0693d222013-06-29 06:16:25159 // Impose an upper limit to avoid out of memory errors that bring down
160 // the process.
161 static const size_t kMaxLength = 0x3fffffff;
162 static ArrayBufferAllocator the_singleton;
163 virtual ~ArrayBufferAllocator() {}
164 virtual void* Allocate(size_t length);
Ben Noordhuisef4a35b2013-10-22 22:17:45165 virtual void* AllocateUninitialized(size_t length);
166 virtual void Free(void* data, size_t length);
Fedor Indutny8e29ce92013-07-31 18:07:29167 private:
Ben Noordhuis0693d222013-06-29 06:16:25168 ArrayBufferAllocator() {}
169 ArrayBufferAllocator(const ArrayBufferAllocator&);
170 void operator=(const ArrayBufferAllocator&);
171};
172
173ArrayBufferAllocator ArrayBufferAllocator::the_singleton;
174
175
176void* ArrayBufferAllocator::Allocate(size_t length) {
Fedor Indutny2bc30f22013-10-16 16:57:26177 if (length > kMaxLength)
178 return NULL;
Trevor Norris72225392013-12-10 01:11:38179 char* data = new char[length];
180 memset(data, 0, length);
181 return data;
Ben Noordhuis0693d222013-06-29 06:16:25182}
183
184
Ben Noordhuisef4a35b2013-10-22 22:17:45185void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
186 if (length > kMaxLength)
187 return NULL;
188 return new char[length];
189}
190
191
192void ArrayBufferAllocator::Free(void* data, size_t length) {
Ben Noordhuis0693d222013-06-29 06:16:25193 delete[] static_cast<char*>(data);
194}
195
196
Saúl Ibarra Corretgé42b93432014-03-12 23:08:29197static void CheckImmediate(uv_check_t* handle) {
Ben Noordhuis756b6222013-08-10 22:26:11198 Environment* env = Environment::from_immediate_check_handle(handle);
Fedor Indutny75adde02014-02-21 13:02:42199 HandleScope scope(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:11200 Context::Scope context_scope(env->context());
201 MakeCallback(env, env->process_object(), env->immediate_callback_string());
Shigeki Ohtsucd372512013-02-06 02:13:02202}
203
204
Saúl Ibarra Corretgé42b93432014-03-12 23:08:29205static void IdleImmediateDummy(uv_idle_t* handle) {
Ben Noordhuis756b6222013-08-10 22:26:11206 // Do nothing. Only for maintaining event loop.
207 // TODO(bnoordhuis) Maybe make libuv accept NULL idle callbacks.
Shigeki Ohtsucd372512013-02-06 02:13:02208}
209
210
Ryan Dahlc9e27b12010-04-23 00:53:45211static inline const char *errno_string(int errorno) {
212#define ERRNO_CASE(e) case e: return #e;
213 switch (errorno) {
Ryan Dahlc9e27b12010-04-23 00:53:45214#ifdef EACCES
215 ERRNO_CASE(EACCES);
216#endif
217
218#ifdef EADDRINUSE
219 ERRNO_CASE(EADDRINUSE);
220#endif
221
222#ifdef EADDRNOTAVAIL
223 ERRNO_CASE(EADDRNOTAVAIL);
224#endif
225
226#ifdef EAFNOSUPPORT
227 ERRNO_CASE(EAFNOSUPPORT);
228#endif
229
230#ifdef EAGAIN
231 ERRNO_CASE(EAGAIN);
Ryan Dahl9b2aac62010-04-28 19:58:00232#endif
233
234#ifdef EWOULDBLOCK
235# if EAGAIN != EWOULDBLOCK
Ryan Dahlc9e27b12010-04-23 00:53:45236 ERRNO_CASE(EWOULDBLOCK);
237# endif
238#endif
239
240#ifdef EALREADY
241 ERRNO_CASE(EALREADY);
242#endif
243
244#ifdef EBADF
245 ERRNO_CASE(EBADF);
246#endif
247
248#ifdef EBADMSG
249 ERRNO_CASE(EBADMSG);
250#endif
251
252#ifdef EBUSY
253 ERRNO_CASE(EBUSY);
254#endif
255
256#ifdef ECANCELED
257 ERRNO_CASE(ECANCELED);
258#endif
259
260#ifdef ECHILD
261 ERRNO_CASE(ECHILD);
262#endif
263
264#ifdef ECONNABORTED
265 ERRNO_CASE(ECONNABORTED);
266#endif
267
268#ifdef ECONNREFUSED
269 ERRNO_CASE(ECONNREFUSED);
270#endif
271
272#ifdef ECONNRESET
273 ERRNO_CASE(ECONNRESET);
274#endif
275
276#ifdef EDEADLK
277 ERRNO_CASE(EDEADLK);
278#endif
279
280#ifdef EDESTADDRREQ
281 ERRNO_CASE(EDESTADDRREQ);
282#endif
283
284#ifdef EDOM
285 ERRNO_CASE(EDOM);
286#endif
287
288#ifdef EDQUOT
289 ERRNO_CASE(EDQUOT);
290#endif
291
292#ifdef EEXIST
293 ERRNO_CASE(EEXIST);
294#endif
295
296#ifdef EFAULT
297 ERRNO_CASE(EFAULT);
298#endif
299
300#ifdef EFBIG
301 ERRNO_CASE(EFBIG);
302#endif
303
304#ifdef EHOSTUNREACH
305 ERRNO_CASE(EHOSTUNREACH);
306#endif
307
308#ifdef EIDRM
309 ERRNO_CASE(EIDRM);
310#endif
311
312#ifdef EILSEQ
313 ERRNO_CASE(EILSEQ);
314#endif
315
316#ifdef EINPROGRESS
317 ERRNO_CASE(EINPROGRESS);
318#endif
319
320#ifdef EINTR
321 ERRNO_CASE(EINTR);
322#endif
323
324#ifdef EINVAL
325 ERRNO_CASE(EINVAL);
326#endif
327
328#ifdef EIO
329 ERRNO_CASE(EIO);
330#endif
331
332#ifdef EISCONN
333 ERRNO_CASE(EISCONN);
334#endif
335
336#ifdef EISDIR
337 ERRNO_CASE(EISDIR);
338#endif
339
340#ifdef ELOOP
341 ERRNO_CASE(ELOOP);
342#endif
343
344#ifdef EMFILE
345 ERRNO_CASE(EMFILE);
346#endif
347
348#ifdef EMLINK
349 ERRNO_CASE(EMLINK);
350#endif
351
352#ifdef EMSGSIZE
353 ERRNO_CASE(EMSGSIZE);
354#endif
355
356#ifdef EMULTIHOP
357 ERRNO_CASE(EMULTIHOP);
358#endif
359
360#ifdef ENAMETOOLONG
361 ERRNO_CASE(ENAMETOOLONG);
362#endif
363
364#ifdef ENETDOWN
365 ERRNO_CASE(ENETDOWN);
366#endif
367
368#ifdef ENETRESET
369 ERRNO_CASE(ENETRESET);
370#endif
371
372#ifdef ENETUNREACH
373 ERRNO_CASE(ENETUNREACH);
374#endif
375
376#ifdef ENFILE
377 ERRNO_CASE(ENFILE);
378#endif
379
380#ifdef ENOBUFS
381 ERRNO_CASE(ENOBUFS);
382#endif
383
384#ifdef ENODATA
385 ERRNO_CASE(ENODATA);
386#endif
387
388#ifdef ENODEV
389 ERRNO_CASE(ENODEV);
390#endif
391
392#ifdef ENOENT
393 ERRNO_CASE(ENOENT);
394#endif
395
396#ifdef ENOEXEC
397 ERRNO_CASE(ENOEXEC);
398#endif
399
Ryan Dahlc9e27b12010-04-23 00:53:45400#ifdef ENOLINK
401 ERRNO_CASE(ENOLINK);
402#endif
403
Ryan Dahl3bb21b52010-04-28 22:07:15404#ifdef ENOLCK
405# if ENOLINK != ENOLCK
406 ERRNO_CASE(ENOLCK);
407# endif
408#endif
409
Ryan Dahlc9e27b12010-04-23 00:53:45410#ifdef ENOMEM
411 ERRNO_CASE(ENOMEM);
412#endif
413
414#ifdef ENOMSG
415 ERRNO_CASE(ENOMSG);
416#endif
417
418#ifdef ENOPROTOOPT
419 ERRNO_CASE(ENOPROTOOPT);
420#endif
421
422#ifdef ENOSPC
423 ERRNO_CASE(ENOSPC);
424#endif
425
426#ifdef ENOSR
427 ERRNO_CASE(ENOSR);
428#endif
429
430#ifdef ENOSTR
431 ERRNO_CASE(ENOSTR);
432#endif
433
434#ifdef ENOSYS
435 ERRNO_CASE(ENOSYS);
436#endif
437
438#ifdef ENOTCONN
439 ERRNO_CASE(ENOTCONN);
440#endif
441
442#ifdef ENOTDIR
443 ERRNO_CASE(ENOTDIR);
444#endif
445
446#ifdef ENOTEMPTY
447 ERRNO_CASE(ENOTEMPTY);
448#endif
449
450#ifdef ENOTSOCK
451 ERRNO_CASE(ENOTSOCK);
452#endif
453
454#ifdef ENOTSUP
455 ERRNO_CASE(ENOTSUP);
456#else
457# ifdef EOPNOTSUPP
458 ERRNO_CASE(EOPNOTSUPP);
459# endif
460#endif
461
462#ifdef ENOTTY
463 ERRNO_CASE(ENOTTY);
464#endif
465
466#ifdef ENXIO
467 ERRNO_CASE(ENXIO);
468#endif
469
470
471#ifdef EOVERFLOW
472 ERRNO_CASE(EOVERFLOW);
473#endif
474
475#ifdef EPERM
476 ERRNO_CASE(EPERM);
477#endif
478
479#ifdef EPIPE
480 ERRNO_CASE(EPIPE);
481#endif
482
483#ifdef EPROTO
484 ERRNO_CASE(EPROTO);
485#endif
486
487#ifdef EPROTONOSUPPORT
488 ERRNO_CASE(EPROTONOSUPPORT);
489#endif
490
491#ifdef EPROTOTYPE
492 ERRNO_CASE(EPROTOTYPE);
493#endif
494
495#ifdef ERANGE
496 ERRNO_CASE(ERANGE);
497#endif
498
499#ifdef EROFS
500 ERRNO_CASE(EROFS);
501#endif
502
503#ifdef ESPIPE
504 ERRNO_CASE(ESPIPE);
505#endif
506
507#ifdef ESRCH
508 ERRNO_CASE(ESRCH);
509#endif
510
511#ifdef ESTALE
512 ERRNO_CASE(ESTALE);
513#endif
514
515#ifdef ETIME
516 ERRNO_CASE(ETIME);
517#endif
518
519#ifdef ETIMEDOUT
520 ERRNO_CASE(ETIMEDOUT);
521#endif
522
523#ifdef ETXTBSY
524 ERRNO_CASE(ETXTBSY);
525#endif
526
527#ifdef EXDEV
528 ERRNO_CASE(EXDEV);
529#endif
530
531 default: return "";
532 }
533}
534
Felix Geisendörferf8a3cf92010-04-28 13:04:08535const char *signo_string(int signo) {
536#define SIGNO_CASE(e) case e: return #e;
537 switch (signo) {
Felix Geisendörferf8a3cf92010-04-28 13:04:08538#ifdef SIGHUP
539 SIGNO_CASE(SIGHUP);
540#endif
541
542#ifdef SIGINT
543 SIGNO_CASE(SIGINT);
544#endif
545
546#ifdef SIGQUIT
547 SIGNO_CASE(SIGQUIT);
548#endif
549
550#ifdef SIGILL
551 SIGNO_CASE(SIGILL);
552#endif
553
554#ifdef SIGTRAP
555 SIGNO_CASE(SIGTRAP);
556#endif
557
558#ifdef SIGABRT
559 SIGNO_CASE(SIGABRT);
560#endif
561
562#ifdef SIGIOT
563# if SIGABRT != SIGIOT
564 SIGNO_CASE(SIGIOT);
565# endif
566#endif
567
568#ifdef SIGBUS
569 SIGNO_CASE(SIGBUS);
570#endif
571
572#ifdef SIGFPE
573 SIGNO_CASE(SIGFPE);
574#endif
575
576#ifdef SIGKILL
577 SIGNO_CASE(SIGKILL);
578#endif
579
580#ifdef SIGUSR1
581 SIGNO_CASE(SIGUSR1);
582#endif
583
584#ifdef SIGSEGV
585 SIGNO_CASE(SIGSEGV);
586#endif
587
588#ifdef SIGUSR2
589 SIGNO_CASE(SIGUSR2);
590#endif
591
592#ifdef SIGPIPE
593 SIGNO_CASE(SIGPIPE);
594#endif
595
596#ifdef SIGALRM
597 SIGNO_CASE(SIGALRM);
598#endif
599
600 SIGNO_CASE(SIGTERM);
Bert Belderdcc35082010-11-25 00:04:31601
602#ifdef SIGCHLD
Felix Geisendörferf8a3cf92010-04-28 13:04:08603 SIGNO_CASE(SIGCHLD);
Bert Belderdcc35082010-11-25 00:04:31604#endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08605
606#ifdef SIGSTKFLT
607 SIGNO_CASE(SIGSTKFLT);
608#endif
609
610
611#ifdef SIGCONT
612 SIGNO_CASE(SIGCONT);
613#endif
614
615#ifdef SIGSTOP
616 SIGNO_CASE(SIGSTOP);
617#endif
618
619#ifdef SIGTSTP
620 SIGNO_CASE(SIGTSTP);
621#endif
622
Bert Belder600a6462012-08-20 21:59:21623#ifdef SIGBREAK
624 SIGNO_CASE(SIGBREAK);
625#endif
626
Felix Geisendörferf8a3cf92010-04-28 13:04:08627#ifdef SIGTTIN
628 SIGNO_CASE(SIGTTIN);
629#endif
630
631#ifdef SIGTTOU
632 SIGNO_CASE(SIGTTOU);
633#endif
634
635#ifdef SIGURG
636 SIGNO_CASE(SIGURG);
637#endif
638
639#ifdef SIGXCPU
640 SIGNO_CASE(SIGXCPU);
641#endif
642
643#ifdef SIGXFSZ
644 SIGNO_CASE(SIGXFSZ);
645#endif
646
647#ifdef SIGVTALRM
648 SIGNO_CASE(SIGVTALRM);
649#endif
650
651#ifdef SIGPROF
652 SIGNO_CASE(SIGPROF);
653#endif
654
655#ifdef SIGWINCH
656 SIGNO_CASE(SIGWINCH);
657#endif
658
659#ifdef SIGIO
660 SIGNO_CASE(SIGIO);
661#endif
662
663#ifdef SIGPOLL
Ryan Dahl3bb21b52010-04-28 22:07:15664# if SIGPOLL != SIGIO
Felix Geisendörferf8a3cf92010-04-28 13:04:08665 SIGNO_CASE(SIGPOLL);
Ryan Dahl3bb21b52010-04-28 22:07:15666# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08667#endif
668
669#ifdef SIGLOST
670 SIGNO_CASE(SIGLOST);
671#endif
672
673#ifdef SIGPWR
Raffaele Senab3b81d62010-06-09 04:08:05674# if SIGPWR != SIGLOST
Felix Geisendörferf8a3cf92010-04-28 13:04:08675 SIGNO_CASE(SIGPWR);
Raffaele Senab3b81d62010-06-09 04:08:05676# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08677#endif
678
679#ifdef SIGSYS
680 SIGNO_CASE(SIGSYS);
681#endif
682
Felix Geisendörferf8a3cf92010-04-28 13:04:08683 default: return "";
684 }
685}
686
Ryan Dahlc9e27b12010-04-23 00:53:45687
Fedor Indutny7b9771f2014-03-17 20:46:40688// Convenience methods
689
690
691void ThrowError(v8::Isolate* isolate, const char* errmsg) {
692 Environment::GetCurrent(isolate)->ThrowError(errmsg);
693}
694
695
696void ThrowTypeError(v8::Isolate* isolate, const char* errmsg) {
697 Environment::GetCurrent(isolate)->ThrowTypeError(errmsg);
698}
699
700
701void ThrowRangeError(v8::Isolate* isolate, const char* errmsg) {
702 Environment::GetCurrent(isolate)->ThrowRangeError(errmsg);
703}
704
705
706void ThrowErrnoException(v8::Isolate* isolate,
707 int errorno,
708 const char* syscall,
709 const char* message,
710 const char* path) {
711 Environment::GetCurrent(isolate)->ThrowErrnoException(errorno,
712 syscall,
713 message,
714 path);
715}
716
717
718void ThrowUVException(v8::Isolate* isolate,
719 int errorno,
720 const char* syscall,
721 const char* message,
722 const char* path) {
723 Environment::GetCurrent(isolate)->ThrowErrnoException(errorno,
724 syscall,
725 message,
726 path);
727}
728
729
Fedor Indutny75adde02014-02-21 13:02:42730Local<Value> ErrnoException(Isolate* isolate,
731 int errorno,
Ryan Dahlc9e27b12010-04-23 00:53:45732 const char *syscall,
visionmedia45948e02010-05-14 14:52:49733 const char *msg,
734 const char *path) {
Fedor Indutny75adde02014-02-21 13:02:42735 Environment* env = Environment::GetCurrent(isolate);
Ben Noordhuis756b6222013-08-10 22:26:11736
visionmedia45948e02010-05-14 14:52:49737 Local<Value> e;
Fedor Indutny75adde02014-02-21 13:02:42738 Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
Ben Noordhuisc679ac82013-07-11 13:37:00739 if (msg == NULL || msg[0] == '\0') {
Bert Belder2ce09612011-01-17 21:47:59740 msg = strerror(errorno);
Bert Belder2ce09612011-01-17 21:47:59741 }
Fedor Indutny75adde02014-02-21 13:02:42742 Local<String> message = OneByteString(env->isolate(), msg);
Ryan Dahlc9e27b12010-04-23 00:53:45743
Ben Noordhuisf674b092013-08-07 19:50:41744 Local<String> cons1 =
Fedor Indutny75adde02014-02-21 13:02:42745 String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
Ryan Dahlc9e27b12010-04-23 00:53:45746 Local<String> cons2 = String::Concat(cons1, message);
747
visionmedia45948e02010-05-14 14:52:49748 if (path) {
Ben Noordhuisf674b092013-08-07 19:50:41749 Local<String> cons3 =
Fedor Indutny75adde02014-02-21 13:02:42750 String::Concat(cons2, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
Ben Noordhuisf674b092013-08-07 19:50:41751 Local<String> cons4 =
Fedor Indutny75adde02014-02-21 13:02:42752 String::Concat(cons3, String::NewFromUtf8(env->isolate(), path));
Ben Noordhuisf674b092013-08-07 19:50:41753 Local<String> cons5 =
Fedor Indutny75adde02014-02-21 13:02:42754 String::Concat(cons4, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
visionmedia45948e02010-05-14 14:52:49755 e = Exception::Error(cons5);
756 } else {
757 e = Exception::Error(cons2);
758 }
759
760 Local<Object> obj = e->ToObject();
Fedor Indutnyce04c722014-03-13 16:38:14761 obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
Ben Noordhuis756b6222013-08-10 22:26:11762 obj->Set(env->code_string(), estring);
visionmedia45948e02010-05-14 14:52:49763
Ben Noordhuis756b6222013-08-10 22:26:11764 if (path != NULL) {
Fedor Indutny75adde02014-02-21 13:02:42765 obj->Set(env->path_string(), String::NewFromUtf8(env->isolate(), path));
Ben Noordhuis756b6222013-08-10 22:26:11766 }
767
768 if (syscall != NULL) {
Fedor Indutny75adde02014-02-21 13:02:42769 obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
Ben Noordhuis756b6222013-08-10 22:26:11770 }
771
Ryan Dahlc9e27b12010-04-23 00:53:45772 return e;
773}
774
775
Bert Belder823a4432011-12-01 23:02:51776// hack alert! copy of ErrnoException, tuned for uv errors
Fedor Indutny75adde02014-02-21 13:02:42777Local<Value> UVException(Isolate* isolate,
778 int errorno,
Bert Belder823a4432011-12-01 23:02:51779 const char *syscall,
780 const char *msg,
781 const char *path) {
Fedor Indutny75adde02014-02-21 13:02:42782 Environment* env = Environment::GetCurrent(isolate);
Bert Belder823a4432011-12-01 23:02:51783
784 if (!msg || !msg[0])
Ben Noordhuisca9eb712013-07-18 21:18:50785 msg = uv_strerror(errorno);
Bert Belder823a4432011-12-01 23:02:51786
Fedor Indutny75adde02014-02-21 13:02:42787 Local<String> estring = OneByteString(env->isolate(), uv_err_name(errorno));
788 Local<String> message = OneByteString(env->isolate(), msg);
Ben Noordhuisf674b092013-08-07 19:50:41789 Local<String> cons1 =
Fedor Indutny75adde02014-02-21 13:02:42790 String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
Bert Belder823a4432011-12-01 23:02:51791 Local<String> cons2 = String::Concat(cons1, message);
792
793 Local<Value> e;
794
795 Local<String> path_str;
796
797 if (path) {
798#ifdef _WIN32
799 if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
Fedor Indutny75adde02014-02-21 13:02:42800 path_str = String::Concat(FIXED_ONE_BYTE_STRING(env->isolate(), "\\\\"),
801 String::NewFromUtf8(env->isolate(), path + 8));
Bert Belder823a4432011-12-01 23:02:51802 } else if (strncmp(path, "\\\\?\\", 4) == 0) {
Fedor Indutny75adde02014-02-21 13:02:42803 path_str = String::NewFromUtf8(env->isolate(), path + 4);
Bert Belder823a4432011-12-01 23:02:51804 } else {
Fedor Indutny75adde02014-02-21 13:02:42805 path_str = String::NewFromUtf8(env->isolate(), path);
Bert Belder823a4432011-12-01 23:02:51806 }
807#else
Fedor Indutny75adde02014-02-21 13:02:42808 path_str = String::NewFromUtf8(env->isolate(), path);
Bert Belder823a4432011-12-01 23:02:51809#endif
810
Ben Noordhuisf674b092013-08-07 19:50:41811 Local<String> cons3 =
Fedor Indutny75adde02014-02-21 13:02:42812 String::Concat(cons2, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
Ben Noordhuisf674b092013-08-07 19:50:41813 Local<String> cons4 =
814 String::Concat(cons3, path_str);
815 Local<String> cons5 =
Fedor Indutny75adde02014-02-21 13:02:42816 String::Concat(cons4, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
Bert Belder823a4432011-12-01 23:02:51817 e = Exception::Error(cons5);
818 } else {
819 e = Exception::Error(cons2);
820 }
821
822 Local<Object> obj = e->ToObject();
Fedor Indutny8e29ce92013-07-31 18:07:29823 // TODO(piscisaureus) errno should probably go
Fedor Indutnyce04c722014-03-13 16:38:14824 obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
Ben Noordhuis756b6222013-08-10 22:26:11825 obj->Set(env->code_string(), estring);
826
827 if (path != NULL) {
828 obj->Set(env->path_string(), path_str);
829 }
830
831 if (syscall != NULL) {
Fedor Indutny75adde02014-02-21 13:02:42832 obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
Ben Noordhuis756b6222013-08-10 22:26:11833 }
834
Bert Belder823a4432011-12-01 23:02:51835 return e;
836}
837
838
Bert Belder6ee73a22011-11-04 15:10:48839#ifdef _WIN32
Igor Zinkovsky500c8f42011-12-15 20:36:05840// Does about the same as strerror(),
841// but supports all windows error messages
Alexis Campailla93f3b642014-08-05 13:33:16842static const char *winapi_strerror(const int errorno, bool* must_free) {
Igor Zinkovsky500c8f42011-12-15 20:36:05843 char *errmsg = NULL;
844
845 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
846 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
847 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
848
849 if (errmsg) {
Alexis Campailla93f3b642014-08-05 13:33:16850 *must_free = true;
851
Igor Zinkovsky500c8f42011-12-15 20:36:05852 // Remove trailing newlines
853 for (int i = strlen(errmsg) - 1;
854 i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
855 errmsg[i] = '\0';
856 }
857
858 return errmsg;
859 } else {
860 // FormatMessage failed
Alexis Campailla93f3b642014-08-05 13:33:16861 *must_free = false;
Igor Zinkovsky500c8f42011-12-15 20:36:05862 return "Unknown error";
863 }
864}
865
866
Alexis Campailla440b9e22014-02-24 18:55:27867Local<Value> WinapiErrnoException(Isolate* isolate,
Fedor Indutny75adde02014-02-21 13:02:42868 int errorno,
Bert Belder829735e2011-11-04 15:23:02869 const char* syscall,
870 const char* msg,
871 const char* path) {
Alexis Campailla440b9e22014-02-24 18:55:27872 Environment* env = Environment::GetCurrent(isolate);
Bert Belder6ee73a22011-11-04 15:10:48873 Local<Value> e;
Alexis Campailla93f3b642014-08-05 13:33:16874 bool must_free = false;
Bert Belder829735e2011-11-04 15:23:02875 if (!msg || !msg[0]) {
Alexis Campailla93f3b642014-08-05 13:33:16876 msg = winapi_strerror(errorno, &must_free);
Bert Belder6ee73a22011-11-04 15:10:48877 }
Fedor Indutny75adde02014-02-21 13:02:42878 Local<String> message = OneByteString(env->isolate(), msg);
Bert Belder6ee73a22011-11-04 15:10:48879
Bert Belder6ee73a22011-11-04 15:10:48880 if (path) {
Ben Noordhuisf674b092013-08-07 19:50:41881 Local<String> cons1 =
Alexis Campailla440b9e22014-02-24 18:55:27882 String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
Ben Noordhuisf674b092013-08-07 19:50:41883 Local<String> cons2 =
Alexis Campailla440b9e22014-02-24 18:55:27884 String::Concat(cons1, String::NewFromUtf8(isolate, path));
Ben Noordhuisf674b092013-08-07 19:50:41885 Local<String> cons3 =
Alexis Campailla440b9e22014-02-24 18:55:27886 String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
Bert Belder6ee73a22011-11-04 15:10:48887 e = Exception::Error(cons3);
888 } else {
889 e = Exception::Error(message);
890 }
891
892 Local<Object> obj = e->ToObject();
Fedor Indutnyce04c722014-03-13 16:38:14893 obj->Set(env->errno_string(), Integer::New(isolate, errorno));
Bert Belder6ee73a22011-11-04 15:10:48894
Ben Noordhuis756b6222013-08-10 22:26:11895 if (path != NULL) {
Alexis Campailla440b9e22014-02-24 18:55:27896 obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
Ben Noordhuis756b6222013-08-10 22:26:11897 }
898
899 if (syscall != NULL) {
Alexis Campailla440b9e22014-02-24 18:55:27900 obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
Ben Noordhuis756b6222013-08-10 22:26:11901 }
902
Alexis Campailla93f3b642014-08-05 13:33:16903 if (must_free)
904 LocalFree((HLOCAL)msg);
905
Bert Belder6ee73a22011-11-04 15:10:48906 return e;
907}
908#endif
909
910
Trevor Norrisefa62fd2013-09-24 21:12:11911void SetupAsyncListener(const FunctionCallbackInfo<Value>& args) {
Trevor Norrisefa62fd2013-09-24 21:12:11912 HandleScope handle_scope(args.GetIsolate());
Ben Noordhuis09724b32013-11-11 21:02:03913 Environment* env = Environment::GetCurrent(args.GetIsolate());
Trevor Norrisefa62fd2013-09-24 21:12:11914
Trevor Norrisbc39bdd2013-10-29 23:35:32915 assert(args[0]->IsObject());
916 assert(args[1]->IsFunction());
917 assert(args[2]->IsFunction());
918 assert(args[3]->IsFunction());
Trevor Norrisefa62fd2013-09-24 21:12:11919
920 env->set_async_listener_run_function(args[1].As<Function>());
921 env->set_async_listener_load_function(args[2].As<Function>());
922 env->set_async_listener_unload_function(args[3].As<Function>());
Trevor Norrisefa62fd2013-09-24 21:12:11923
924 Local<Object> async_listener_flag_obj = args[0].As<Object>();
925 Environment::AsyncListener* async_listener = env->async_listener();
926 async_listener_flag_obj->SetIndexedPropertiesToExternalArrayData(
927 async_listener->fields(),
Trevor Norrisbdc2ea42014-10-08 08:34:46928 kExternalUint32Array,
Trevor Norrisefa62fd2013-09-24 21:12:11929 async_listener->fields_count());
930
931 // Do a little housekeeping.
932 env->process_object()->Delete(
933 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupAsyncListener"));
934}
935
936
Trevor Norris828f1452014-01-09 19:11:40937void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
938 Environment* env = Environment::GetCurrent(args.GetIsolate());
939
940 if (env->using_domains())
941 return;
942 env->set_using_domains(true);
943
Fedor Indutny75adde02014-02-21 13:02:42944 HandleScope scope(env->isolate());
Trevor Norris828f1452014-01-09 19:11:40945 Local<Object> process_object = env->process_object();
946
Fedor Indutny75adde02014-02-21 13:02:42947 Local<String> tick_callback_function_key = env->tick_domain_cb_string();
Trevor Norris828f1452014-01-09 19:11:40948 Local<Function> tick_callback_function =
949 process_object->Get(tick_callback_function_key).As<Function>();
950
951 if (!tick_callback_function->IsFunction()) {
952 fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
953 abort();
954 }
955
Fedor Indutny75adde02014-02-21 13:02:42956 process_object->Set(env->tick_callback_string(), tick_callback_function);
Trevor Norris828f1452014-01-09 19:11:40957 env->set_tick_callback_function(tick_callback_function);
958
959 assert(args[0]->IsArray());
960 assert(args[1]->IsObject());
961
962 env->set_domain_array(args[0].As<Array>());
963
964 Local<Object> domain_flag_obj = args[1].As<Object>();
965 Environment::DomainFlag* domain_flag = env->domain_flag();
966 domain_flag_obj->SetIndexedPropertiesToExternalArrayData(
967 domain_flag->fields(),
Trevor Norrisbdc2ea42014-10-08 08:34:46968 kExternalUint32Array,
Trevor Norris828f1452014-01-09 19:11:40969 domain_flag->fields_count());
970
971 // Do a little housekeeping.
972 env->process_object()->Delete(
973 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse"));
974}
975
Vladimir Kurchatkin30bd7b62014-09-04 16:02:04976void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
977 args.GetIsolate()->RunMicrotasks();
978}
979
Trevor Norris828f1452014-01-09 19:11:40980
Trevor Norrisefa62fd2013-09-24 21:12:11981void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
Trevor Norrisefa62fd2013-09-24 21:12:11982 HandleScope handle_scope(args.GetIsolate());
Ben Noordhuis09724b32013-11-11 21:02:03983 Environment* env = Environment::GetCurrent(args.GetIsolate());
Trevor Norrisefa62fd2013-09-24 21:12:11984
Trevor Norris828f1452014-01-09 19:11:40985 assert(args[0]->IsObject());
986 assert(args[1]->IsFunction());
Vladimir Kurchatkin30bd7b62014-09-04 16:02:04987 assert(args[2]->IsObject());
Trevor Norrisefa62fd2013-09-24 21:12:11988
989 // Values use to cross communicate with processNextTick.
990 Local<Object> tick_info_obj = args[0].As<Object>();
991 tick_info_obj->SetIndexedPropertiesToExternalArrayData(
992 env->tick_info()->fields(),
Trevor Norrisbdc2ea42014-10-08 08:34:46993 kExternalUint32Array,
Trevor Norrisefa62fd2013-09-24 21:12:11994 env->tick_info()->fields_count());
995
996 env->set_tick_callback_function(args[1].As<Function>());
997
Vladimir Kurchatkin30bd7b62014-09-04 16:02:04998 NODE_SET_METHOD(args[2].As<Object>(), "runMicrotasks", RunMicrotasks);
999
Trevor Norrisefa62fd2013-09-24 21:12:111000 // Do a little housekeeping.
1001 env->process_object()->Delete(
1002 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick"));
Trevor Norris3f5d5842013-08-07 00:01:441003}
1004
1005
Trevor Norris828f1452014-01-09 19:11:401006Handle<Value> MakeDomainCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161007 Handle<Value> recv,
Trevor Norris828f1452014-01-09 19:11:401008 const Handle<Function> callback,
1009 int argc,
1010 Handle<Value> argv[]) {
1011 // If you hit this assertion, you forgot to enter the v8::Context first.
1012 assert(env->context() == env->isolate()->GetCurrentContext());
1013
1014 Local<Object> process = env->process_object();
Ben Noordhuis1f2f3fa2014-01-27 02:58:161015 Local<Object> object, domain;
1016 Local<Value> domain_v;
Trevor Norris828f1452014-01-09 19:11:401017
1018 TryCatch try_catch;
1019 try_catch.SetVerbose(true);
1020
Ben Noordhuis1f2f3fa2014-01-27 02:58:161021 bool has_async_queue = false;
Trevor Norris828f1452014-01-09 19:11:401022
Ben Noordhuis1f2f3fa2014-01-27 02:58:161023 if (recv->IsObject()) {
1024 object = recv.As<Object>();
1025 // TODO(trevnorris): This is sucky for performance. Fix it.
1026 has_async_queue = object->Has(env->async_queue_string());
1027 if (has_async_queue) {
1028 env->async_listener_load_function()->Call(process, 1, &recv);
Trevor Norris828f1452014-01-09 19:11:401029
Ben Noordhuis1f2f3fa2014-01-27 02:58:161030 if (try_catch.HasCaught())
Fedor Indutny75adde02014-02-21 13:02:421031 return Undefined(env->isolate());
Trevor Norris828f1452014-01-09 19:11:401032 }
1033 }
1034
Ben Noordhuis1f2f3fa2014-01-27 02:58:161035 bool has_domain = false;
1036
1037 if (!object.IsEmpty()) {
1038 domain_v = object->Get(env->domain_string());
1039 has_domain = domain_v->IsObject();
1040 if (has_domain) {
1041 domain = domain_v.As<Object>();
1042
1043 if (domain->Get(env->disposed_string())->IsTrue()) {
1044 // domain has been disposed of.
Fedor Indutny75adde02014-02-21 13:02:421045 return Undefined(env->isolate());
Ben Noordhuis1f2f3fa2014-01-27 02:58:161046 }
1047
Trevor Norris81a97392014-09-02 18:30:451048 Local<Function> enter = domain->Get(env->enter_string()).As<Function>();
1049 if (enter->IsFunction()) {
1050 enter->Call(domain, 0, NULL);
1051 if (try_catch.HasCaught())
1052 return Undefined(env->isolate());
Ben Noordhuis1f2f3fa2014-01-27 02:58:161053 }
1054 }
1055 }
1056
1057 Local<Value> ret = callback->Call(recv, argc, argv);
Trevor Norris828f1452014-01-09 19:11:401058
1059 if (try_catch.HasCaught()) {
Fedor Indutny75adde02014-02-21 13:02:421060 return Undefined(env->isolate());
Trevor Norris828f1452014-01-09 19:11:401061 }
1062
1063 if (has_domain) {
Trevor Norris81a97392014-09-02 18:30:451064 Local<Function> exit = domain->Get(env->exit_string()).As<Function>();
1065 if (exit->IsFunction()) {
1066 exit->Call(domain, 0, NULL);
1067 if (try_catch.HasCaught())
1068 return Undefined(env->isolate());
Trevor Norris828f1452014-01-09 19:11:401069 }
1070 }
1071
1072 if (has_async_queue) {
Ben Noordhuis1f2f3fa2014-01-27 02:58:161073 env->async_listener_unload_function()->Call(process, 1, &recv);
Trevor Norris828f1452014-01-09 19:11:401074
1075 if (try_catch.HasCaught())
Fedor Indutny75adde02014-02-21 13:02:421076 return Undefined(env->isolate());
Trevor Norris828f1452014-01-09 19:11:401077 }
1078
1079 Environment::TickInfo* tick_info = env->tick_info();
1080
1081 if (tick_info->last_threw() == 1) {
1082 tick_info->set_last_threw(0);
1083 return ret;
1084 }
1085
1086 if (tick_info->in_tick()) {
1087 return ret;
1088 }
1089
1090 if (tick_info->length() == 0) {
Vladimir Kurchatkin8dc6be12014-09-22 16:19:501091 env->isolate()->RunMicrotasks();
1092 }
1093
1094 if (tick_info->length() == 0) {
Trevor Norris828f1452014-01-09 19:11:401095 tick_info->set_index(0);
1096 return ret;
1097 }
1098
1099 tick_info->set_in_tick(true);
1100
1101 env->tick_callback_function()->Call(process, 0, NULL);
1102
1103 tick_info->set_in_tick(false);
1104
1105 if (try_catch.HasCaught()) {
1106 tick_info->set_last_threw(true);
Fedor Indutny75adde02014-02-21 13:02:421107 return Undefined(env->isolate());
Trevor Norris828f1452014-01-09 19:11:401108 }
1109
1110 return ret;
1111}
1112
1113
Ben Noordhuis756b6222013-08-10 22:26:111114Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161115 Handle<Value> recv,
Ben Noordhuis756b6222013-08-10 22:26:111116 const Handle<Function> callback,
1117 int argc,
1118 Handle<Value> argv[]) {
Trevor Norris828f1452014-01-09 19:11:401119 if (env->using_domains())
Ben Noordhuis1f2f3fa2014-01-27 02:58:161120 return MakeDomainCallback(env, recv, callback, argc, argv);
Trevor Norris828f1452014-01-09 19:11:401121
Trevor Norrisefa62fd2013-09-24 21:12:111122 // If you hit this assertion, you forgot to enter the v8::Context first.
1123 assert(env->context() == env->isolate()->GetCurrentContext());
1124
1125 Local<Object> process = env->process_object();
1126
Trevor Norris86c07452013-02-07 01:26:181127 TryCatch try_catch;
Miroslav Bajtosc16963b2013-06-17 19:19:591128 try_catch.SetVerbose(true);
Trevor Norris86c07452013-02-07 01:26:181129
Trevor Norrisefa62fd2013-09-24 21:12:111130 // TODO(trevnorris): This is sucky for performance. Fix it.
Ben Noordhuis1f2f3fa2014-01-27 02:58:161131 bool has_async_queue =
1132 recv->IsObject() && recv.As<Object>()->Has(env->async_queue_string());
Trevor Norrisefa62fd2013-09-24 21:12:111133 if (has_async_queue) {
Ben Noordhuis1f2f3fa2014-01-27 02:58:161134 env->async_listener_load_function()->Call(process, 1, &recv);
Trevor Norrisefa62fd2013-09-24 21:12:111135 if (try_catch.HasCaught())
Fedor Indutny75adde02014-02-21 13:02:421136 return Undefined(env->isolate());
Trevor Norrisefa62fd2013-09-24 21:12:111137 }
1138
Ben Noordhuis1f2f3fa2014-01-27 02:58:161139 Local<Value> ret = callback->Call(recv, argc, argv);
isaacs10ce3d12012-04-13 23:27:231140
1141 if (try_catch.HasCaught()) {
Fedor Indutny75adde02014-02-21 13:02:421142 return Undefined(env->isolate());
Ryan Dahl650a3082011-05-28 20:44:031143 }
isaacsac1aadd2012-04-13 23:34:481144
Trevor Norrisefa62fd2013-09-24 21:12:111145 if (has_async_queue) {
Ben Noordhuis1f2f3fa2014-01-27 02:58:161146 env->async_listener_unload_function()->Call(process, 1, &recv);
Trevor Norrisefa62fd2013-09-24 21:12:111147
1148 if (try_catch.HasCaught())
Fedor Indutny75adde02014-02-21 13:02:421149 return Undefined(env->isolate());
Trevor Norrisefa62fd2013-09-24 21:12:111150 }
1151
Ben Noordhuis756b6222013-08-10 22:26:111152 Environment::TickInfo* tick_info = env->tick_info();
1153
Trevor Norrisefa62fd2013-09-24 21:12:111154 if (tick_info->in_tick()) {
Trevor Norris6a5a7b02013-07-30 22:06:451155 return ret;
1156 }
1157
Ben Noordhuis756b6222013-08-10 22:26:111158 if (tick_info->length() == 0) {
Vladimir Kurchatkin8dc6be12014-09-22 16:19:501159 env->isolate()->RunMicrotasks();
1160 }
1161
1162 if (tick_info->length() == 0) {
Ben Noordhuis756b6222013-08-10 22:26:111163 tick_info->set_index(0);
Trevor Norrisa0867e12013-03-17 04:59:471164 return ret;
Trevor Norrisec420002013-02-13 14:30:061165 }
1166
Trevor Norris4b84e422013-08-27 18:30:061167 tick_info->set_in_tick(true);
1168
Trevor Norris86c07452013-02-07 01:26:181169 // process nextTicks after call
Trevor Norrisefa62fd2013-09-24 21:12:111170 env->tick_callback_function()->Call(process, 0, NULL);
Trevor Norris86c07452013-02-07 01:26:181171
Trevor Norris4b84e422013-08-27 18:30:061172 tick_info->set_in_tick(false);
1173
Trevor Norris86c07452013-02-07 01:26:181174 if (try_catch.HasCaught()) {
Trevor Norris4b84e422013-08-27 18:30:061175 tick_info->set_last_threw(true);
Fedor Indutny75adde02014-02-21 13:02:421176 return Undefined(env->isolate());
Trevor Norris86c07452013-02-07 01:26:181177 }
1178
Trevor Norrisa0867e12013-03-17 04:59:471179 return ret;
1180}
1181
1182
Ben Noordhuis7a3f7782013-08-15 17:22:441183// Internal only.
Ben Noordhuis756b6222013-08-10 22:26:111184Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161185 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111186 uint32_t index,
1187 int argc,
1188 Handle<Value> argv[]) {
Ben Noordhuis1f2f3fa2014-01-27 02:58:161189 Local<Function> callback = recv->Get(index).As<Function>();
Ben Noordhuis7a3f7782013-08-15 17:22:441190 assert(callback->IsFunction());
1191
Ben Noordhuis1f2f3fa2014-01-27 02:58:161192 return MakeCallback(env, recv.As<Value>(), callback, argc, argv);
Ben Noordhuis7a3f7782013-08-15 17:22:441193}
1194
1195
Ben Noordhuis756b6222013-08-10 22:26:111196Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161197 Handle<Object> recv,
1198 Handle<String> symbol,
Ben Noordhuis756b6222013-08-10 22:26:111199 int argc,
1200 Handle<Value> argv[]) {
Ben Noordhuis1f2f3fa2014-01-27 02:58:161201 Local<Function> callback = recv->Get(symbol).As<Function>();
Ben Noordhuisdb139832013-06-02 13:11:461202 assert(callback->IsFunction());
Ben Noordhuis1f2f3fa2014-01-27 02:58:161203 return MakeCallback(env, recv.As<Value>(), callback, argc, argv);
Trevor Norris86c07452013-02-07 01:26:181204}
1205
1206
Ben Noordhuis756b6222013-08-10 22:26:111207Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161208 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111209 const char* method,
1210 int argc,
1211 Handle<Value> argv[]) {
Fedor Indutny75adde02014-02-21 13:02:421212 Local<String> method_string = OneByteString(env->isolate(), method);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161213 return MakeCallback(env, recv, method_string, argc, argv);
Ben Noordhuis756b6222013-08-10 22:26:111214}
Trevor Norris86c07452013-02-07 01:26:181215
Ben Noordhuis756b6222013-08-10 22:26:111216
Fedor Indutny75adde02014-02-21 13:02:421217Handle<Value> MakeCallback(Isolate* isolate,
1218 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111219 const char* method,
1220 int argc,
1221 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141222 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161223 Local<Context> context = recv->CreationContext();
Ben Noordhuis756b6222013-08-10 22:26:111224 Environment* env = Environment::GetCurrent(context);
1225 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141226 return handle_scope.Escape(
1227 Local<Value>::New(isolate, MakeCallback(env, recv, method, argc, argv)));
Ben Noordhuis756b6222013-08-10 22:26:111228}
1229
1230
Fedor Indutny75adde02014-02-21 13:02:421231Handle<Value> MakeCallback(Isolate* isolate,
1232 Handle<Object> recv,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161233 Handle<String> symbol,
Ben Noordhuis756b6222013-08-10 22:26:111234 int argc,
1235 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141236 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161237 Local<Context> context = recv->CreationContext();
Ben Noordhuis756b6222013-08-10 22:26:111238 Environment* env = Environment::GetCurrent(context);
1239 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141240 return handle_scope.Escape(
1241 Local<Value>::New(isolate, MakeCallback(env, recv, symbol, argc, argv)));
Ben Noordhuis756b6222013-08-10 22:26:111242}
1243
1244
Fedor Indutny75adde02014-02-21 13:02:421245Handle<Value> MakeCallback(Isolate* isolate,
1246 Handle<Object> recv,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161247 Handle<Function> callback,
Ben Noordhuis756b6222013-08-10 22:26:111248 int argc,
1249 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141250 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161251 Local<Context> context = recv->CreationContext();
Trevor Norris828f1452014-01-09 19:11:401252 Environment* env = Environment::GetCurrent(context);
1253 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141254 return handle_scope.Escape(Local<Value>::New(
1255 isolate,
1256 MakeCallback(env, recv.As<Value>(), callback, argc, argv)));
Ben Noordhuis1f2f3fa2014-01-27 02:58:161257}
1258
1259
1260Handle<Value> MakeDomainCallback(Handle<Object> recv,
1261 Handle<Function> callback,
1262 int argc,
1263 Handle<Value> argv[]) {
1264 Local<Context> context = recv->CreationContext();
1265 Environment* env = Environment::GetCurrent(context);
1266 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141267 EscapableHandleScope handle_scope(env->isolate());
1268 return handle_scope.Escape(Local<Value>::New(
1269 env->isolate(),
1270 MakeDomainCallback(env, recv, callback, argc, argv)));
Trevor Norris828f1452014-01-09 19:11:401271}
1272
1273
Fedor Indutny75adde02014-02-21 13:02:421274enum encoding ParseEncoding(Isolate* isolate,
1275 Handle<Value> encoding_v,
1276 enum encoding _default) {
1277 HandleScope scope(isolate);
Ryan Dahl07792af2009-09-21 10:27:221278
Fedor Indutny2bc30f22013-10-16 16:57:261279 if (!encoding_v->IsString())
1280 return _default;
Ryan Dahl07792af2009-09-21 10:27:221281
Timothy J Fontaine535c7772014-04-10 00:33:331282 node::Utf8Value encoding(encoding_v);
Ryan Dahl07792af2009-09-21 10:27:221283
1284 if (strcasecmp(*encoding, "utf8") == 0) {
1285 return UTF8;
Ryan Dahl2b994d92009-10-06 08:45:181286 } else if (strcasecmp(*encoding, "utf-8") == 0) {
1287 return UTF8;
Ryan Dahl07792af2009-09-21 10:27:221288 } else if (strcasecmp(*encoding, "ascii") == 0) {
1289 return ASCII;
Ben Noordhuis95638c92010-07-28 12:20:231290 } else if (strcasecmp(*encoding, "base64") == 0) {
1291 return BASE64;
Konstantin Käfer9e101f22011-02-06 20:49:521292 } else if (strcasecmp(*encoding, "ucs2") == 0) {
1293 return UCS2;
1294 } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1295 return UCS2;
koichikfbb0ee62012-10-02 14:57:381296 } else if (strcasecmp(*encoding, "utf16le") == 0) {
1297 return UCS2;
1298 } else if (strcasecmp(*encoding, "utf-16le") == 0) {
1299 return UCS2;
Ryan Dahl07792af2009-09-21 10:27:221300 } else if (strcasecmp(*encoding, "binary") == 0) {
1301 return BINARY;
Fedor Indutny63ff4492012-09-12 20:35:591302 } else if (strcasecmp(*encoding, "buffer") == 0) {
1303 return BUFFER;
isaacs0aa1a8a2011-02-20 01:29:011304 } else if (strcasecmp(*encoding, "hex") == 0) {
1305 return HEX;
Ryan Dahl07792af2009-09-21 10:27:221306 } else if (strcasecmp(*encoding, "raw") == 0) {
isaacs5b399292012-06-21 18:42:331307 if (!no_deprecation) {
1308 fprintf(stderr, "'raw' (array of integers) has been removed. "
1309 "Use 'binary'.\n");
1310 }
Ryan Dahl07792af2009-09-21 10:27:221311 return BINARY;
1312 } else if (strcasecmp(*encoding, "raws") == 0) {
isaacs5b399292012-06-21 18:42:331313 if (!no_deprecation) {
1314 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1315 "Please update your code.\n");
1316 }
Ryan Dahl07792af2009-09-21 10:27:221317 return BINARY;
1318 } else {
1319 return _default;
1320 }
1321}
1322
Fedor Indutny75adde02014-02-21 13:02:421323Local<Value> Encode(Isolate* isolate,
1324 const void* buf,
1325 size_t len,
1326 enum encoding encoding) {
1327 return StringBytes::Encode(isolate,
1328 static_cast<const char*>(buf),
isaacs4e8cddd2013-05-02 17:49:201329 len,
1330 encoding);
Ryan21a1b042009-09-09 13:51:491331}
1332
Ryand6c9d312009-09-11 14:02:291333// Returns -1 if the handle was not valid for decoding
Fedor Indutny75adde02014-02-21 13:02:421334ssize_t DecodeBytes(Isolate* isolate,
1335 Handle<Value> val,
1336 enum encoding encoding) {
1337 HandleScope scope(isolate);
Ryan21a1b042009-09-09 13:51:491338
1339 if (val->IsArray()) {
isaacsa3753b42012-05-16 23:32:371340 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1341 "Use 'binary'.\n");
Ryan Dahl07792af2009-09-21 10:27:221342 assert(0);
1343 return -1;
Ryan21a1b042009-09-09 13:51:491344 }
1345
Fedor Indutny75adde02014-02-21 13:02:421346 return StringBytes::Size(isolate, val, encoding);
Ryan21a1b042009-09-09 13:51:491347}
1348
1349#ifndef MIN
Ryand6c9d312009-09-11 14:02:291350# define MIN(a, b) ((a) < (b) ? (a) : (b))
Ryan21a1b042009-09-09 13:51:491351#endif
1352
1353// Returns number of bytes written.
Fedor Indutny75adde02014-02-21 13:02:421354ssize_t DecodeWrite(Isolate* isolate,
1355 char* buf,
Ryan Dahl53530e92010-04-02 21:55:281356 size_t buflen,
Fedor Indutny75adde02014-02-21 13:02:421357 Handle<Value> val,
Ryand6c9d312009-09-11 14:02:291358 enum encoding encoding) {
Fedor Indutny75adde02014-02-21 13:02:421359 return StringBytes::Write(isolate, buf, buflen, val, encoding, NULL);
Ryan21a1b042009-09-09 13:51:491360}
1361
Fedor Indutnyf1de13b2014-02-05 16:38:331362void AppendExceptionLine(Environment* env,
1363 Handle<Value> er,
1364 Handle<Message> message) {
1365 if (message.IsEmpty())
Fedor Indutny2bc30f22013-10-16 16:57:261366 return;
isaacsb3cf3f32012-07-28 21:00:271367
Fedor Indutnyf1de13b2014-02-05 16:38:331368 HandleScope scope(env->isolate());
1369 Local<Object> err_obj;
1370 if (!er.IsEmpty() && er->IsObject()) {
1371 err_obj = er.As<Object>();
Ryan Dahlcdf5d912011-10-11 20:41:331372
Fedor Indutnyf1de13b2014-02-05 16:38:331373 // Do it only once per message
1374 if (!err_obj->GetHiddenValue(env->processed_string()).IsEmpty())
1375 return;
1376 err_obj->SetHiddenValue(env->processed_string(), True(env->isolate()));
Ryan Dahl8e6dd522010-01-15 18:45:041377 }
Fedor Indutnyf1de13b2014-02-05 16:38:331378
1379 static char arrow[1024];
1380
1381 // Print (filename):(line number): (message).
Timothy J Fontaine1a09da62014-06-10 23:36:041382 node::Utf8Value filename(message->GetScriptResourceName());
Fedor Indutnyf1de13b2014-02-05 16:38:331383 const char* filename_string = *filename;
1384 int linenum = message->GetLineNumber();
1385 // Print line of source code.
Timothy J Fontaine1a09da62014-06-10 23:36:041386 node::Utf8Value sourceline(message->GetSourceLine());
Fedor Indutnyf1de13b2014-02-05 16:38:331387 const char* sourceline_string = *sourceline;
1388
1389 // Because of how node modules work, all scripts are wrapped with a
1390 // "function (module, exports, __filename, ...) {"
1391 // to provide script local variables.
1392 //
1393 // When reporting errors on the first line of a script, this wrapper
1394 // function is leaked to the user. There used to be a hack here to
1395 // truncate off the first 62 characters, but it caused numerous other
1396 // problems when vm.runIn*Context() methods were used for non-module
1397 // code.
1398 //
1399 // If we ever decide to re-instate such a hack, the following steps
1400 // must be taken:
1401 //
1402 // 1. Pass a flag around to say "this code was wrapped"
1403 // 2. Update the stack frame output so that it is also correct.
1404 //
1405 // It would probably be simpler to add a line rather than add some
1406 // number of characters to the first line, since V8 truncates the
1407 // sourceline to 78 characters, and we end up not providing very much
1408 // useful debugging info to the user if we remove 62 characters.
1409
1410 int start = message->GetStartColumn();
1411 int end = message->GetEndColumn();
1412
1413 int off = snprintf(arrow,
1414 sizeof(arrow),
1415 "%s:%i\n%s\n",
1416 filename_string,
1417 linenum,
1418 sourceline_string);
1419 assert(off >= 0);
1420
1421 // Print wavy underline (GetUnderline is deprecated).
1422 for (int i = 0; i < start; i++) {
Yazhong Liu6b09f9c2014-06-25 13:18:501423 if (sourceline_string[i] == '\0' ||
1424 static_cast<size_t>(off) >= sizeof(arrow)) {
1425 break;
1426 }
Fedor Indutnyf1de13b2014-02-05 16:38:331427 assert(static_cast<size_t>(off) < sizeof(arrow));
1428 arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1429 }
1430 for (int i = start; i < end; i++) {
Yazhong Liu6b09f9c2014-06-25 13:18:501431 if (sourceline_string[i] == '\0' ||
1432 static_cast<size_t>(off) >= sizeof(arrow)) {
1433 break;
1434 }
Fedor Indutnyf1de13b2014-02-05 16:38:331435 assert(static_cast<size_t>(off) < sizeof(arrow));
1436 arrow[off++] = '^';
1437 }
Yazhong Liu6b09f9c2014-06-25 13:18:501438 assert(static_cast<size_t>(off - 1) <= sizeof(arrow) - 1);
Fedor Indutnyf1de13b2014-02-05 16:38:331439 arrow[off++] = '\n';
1440 arrow[off] = '\0';
1441
1442 Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1443 Local<Value> msg;
1444 Local<Value> stack;
1445
1446 // Allocation failed, just print it out
1447 if (arrow_str.IsEmpty() || err_obj.IsEmpty() || !err_obj->IsNativeError())
1448 goto print;
1449
1450 msg = err_obj->Get(env->message_string());
1451 stack = err_obj->Get(env->stack_string());
1452
1453 if (msg.IsEmpty() || stack.IsEmpty())
1454 goto print;
1455
1456 err_obj->Set(env->message_string(),
1457 String::Concat(arrow_str, msg->ToString()));
1458 err_obj->Set(env->stack_string(),
1459 String::Concat(arrow_str, stack->ToString()));
1460 return;
1461
1462 print:
1463 if (env->printed_error())
1464 return;
1465 env->set_printed_error(true);
1466 uv_tty_reset_mode();
1467 fprintf(stderr, "\n%s", arrow);
Ryan Dahlb57c1f52010-11-24 02:46:131468}
1469
1470
Fedor Indutnyf1de13b2014-02-05 16:38:331471static void ReportException(Environment* env,
1472 Handle<Value> er,
1473 Handle<Message> message) {
1474 HandleScope scope(env->isolate());
Ryan Dahlb57c1f52010-11-24 02:46:131475
Fedor Indutnyf1de13b2014-02-05 16:38:331476 AppendExceptionLine(env, er, message);
Ryan Dahl53a841d2009-12-29 19:20:511477
Vladimir Kurchatkin259d4492013-12-06 11:56:371478 Local<Value> trace_value;
1479
Fedor Indutnyf1de13b2014-02-05 16:38:331480 if (er->IsUndefined() || er->IsNull())
1481 trace_value = Undefined(env->isolate());
1482 else
1483 trace_value = er->ToObject()->Get(env->stack_string());
Vladimir Kurchatkin259d4492013-12-06 11:56:371484
Timothy J Fontaine1a09da62014-06-10 23:36:041485 node::Utf8Value trace(trace_value);
Ryan Dahlda932302010-05-14 18:48:141486
isaacs8df6f9e2011-04-25 19:22:181487 // range errors have a trace member set to undefined
Miroslav Bajtosc16963b2013-06-17 19:19:591488 if (trace.length() > 0 && !trace_value->IsUndefined()) {
Ryanafd9e712009-08-31 16:22:091489 fprintf(stderr, "%s\n", *trace);
isaacse9b6b0b2010-10-02 06:22:341490 } else {
1491 // this really only happens for RangeErrors, since they're the only
isaacs8df6f9e2011-04-25 19:22:181492 // kind that won't have all this info in the trace, or when non-Error
1493 // objects are thrown manually.
Ben Noordhuisf674b092013-08-07 19:50:411494 Local<Value> message;
1495 Local<Value> name;
isaacs8df6f9e2011-04-25 19:22:181496
Ben Noordhuisf674b092013-08-07 19:50:411497 if (er->IsObject()) {
1498 Local<Object> err_obj = er.As<Object>();
Fedor Indutnyf1de13b2014-02-05 16:38:331499 message = err_obj->Get(env->message_string());
1500 name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
isaacs8df6f9e2011-04-25 19:22:181501 }
1502
Ben Noordhuisf674b092013-08-07 19:50:411503 if (message.IsEmpty() ||
1504 message->IsUndefined() ||
1505 name.IsEmpty() ||
1506 name->IsUndefined()) {
1507 // Not an error object. Just print as-is.
Timothy J Fontaine1a09da62014-06-10 23:36:041508 node::Utf8Value message(er);
Ben Noordhuisf674b092013-08-07 19:50:411509 fprintf(stderr, "%s\n", *message);
1510 } else {
Timothy J Fontaine1a09da62014-06-10 23:36:041511 node::Utf8Value name_string(name);
1512 node::Utf8Value message_string(message);
Ben Noordhuisf674b092013-08-07 19:50:411513 fprintf(stderr, "%s: %s\n", *name_string, *message_string);
1514 }
Ryan5131e0a2009-03-09 00:23:411515 }
isaacse9b6b0b2010-10-02 06:22:341516
Ryand7e220c2009-09-09 20:35:401517 fflush(stderr);
Ryan5131e0a2009-03-09 00:23:411518}
1519
Miroslav Bajtosc16963b2013-06-17 19:19:591520
Fedor Indutnyf1de13b2014-02-05 16:38:331521static void ReportException(Environment* env, const TryCatch& try_catch) {
1522 ReportException(env, try_catch.Exception(), try_catch.Message());
Miroslav Bajtosc16963b2013-06-17 19:19:591523}
1524
1525
Ryand6c9d312009-09-11 14:02:291526// Executes a str within the current v8 context.
Fedor Indutnyf1de13b2014-02-05 16:38:331527static Local<Value> ExecuteString(Environment* env,
1528 Handle<String> source,
Ben Noordhuisc7214fe2014-03-31 13:13:371529 Handle<String> filename) {
Fedor Indutnyce04c722014-03-13 16:38:141530 EscapableHandleScope scope(env->isolate());
Ryan408526a2009-04-21 11:52:211531 TryCatch try_catch;
1532
Miroslav Bajtosc16963b2013-06-17 19:19:591533 // try_catch must be nonverbose to disable FatalException() handler,
1534 // we will handle exceptions ourself.
1535 try_catch.SetVerbose(false);
1536
Herbert Vojcikc2a06722010-04-17 15:18:151537 Local<v8::Script> script = v8::Script::Compile(source, filename);
Ryan63a9cd32009-04-15 08:08:281538 if (script.IsEmpty()) {
Fedor Indutnyf1de13b2014-02-05 16:38:331539 ReportException(env, try_catch);
isaacs95862b22013-02-27 19:23:201540 exit(3);
Ryan63a9cd32009-04-15 08:08:281541 }
1542
Ryan Dahl9f5643f2010-01-31 07:22:341543 Local<Value> result = script->Run();
Ryan63a9cd32009-04-15 08:08:281544 if (result.IsEmpty()) {
Fedor Indutnyf1de13b2014-02-05 16:38:331545 ReportException(env, try_catch);
isaacs95862b22013-02-27 19:23:201546 exit(4);
Ryan63a9cd32009-04-15 08:08:281547 }
1548
Fedor Indutnyce04c722014-03-13 16:38:141549 return scope.Escape(result);
Ryan63a9cd32009-04-15 08:08:281550}
1551
Felix Geisendörfer7371fcb2009-11-11 17:10:581552
Ben Noordhuis110a9cd2013-07-03 02:23:441553static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny6a610a02014-10-04 14:44:391554 Environment* env = Environment::GetCurrent(args.GetIsolate());
1555 HandleScope scope(env->isolate());
Ben Noordhuis5f040652012-04-28 16:45:101556
Fedor Indutnyce04c722014-03-13 16:38:141557 Local<Array> ary = Array::New(args.GetIsolate());
Ben Noordhuisa7820a12013-06-04 10:21:581558 QUEUE* q = NULL;
Ben Noordhuis5f040652012-04-28 16:45:101559 int i = 0;
1560
Fedor Indutny6a610a02014-10-04 14:44:391561 QUEUE_FOREACH(q, env->req_wrap_queue()) {
Ben Noordhuis820aaf52014-05-27 21:31:311562 ReqWrap<uv_req_t>* w = ContainerOf(&ReqWrap<uv_req_t>::req_wrap_queue_, q);
Fedor Indutny2bc30f22013-10-16 16:57:261563 if (w->persistent().IsEmpty())
1564 continue;
Ben Noordhuis110a9cd2013-07-03 02:23:441565 ary->Set(i++, w->object());
Ben Noordhuis5f040652012-04-28 16:45:101566 }
1567
Ben Noordhuis110a9cd2013-07-03 02:23:441568 args.GetReturnValue().Set(ary);
Ben Noordhuis5f040652012-04-28 16:45:101569}
1570
1571
1572// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1573// implemented here for consistency with GetActiveRequests().
Ben Noordhuis110a9cd2013-07-03 02:23:441574void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421575 Environment* env = Environment::GetCurrent(args.GetIsolate());
1576 HandleScope scope(env->isolate());
Ben Noordhuis5f040652012-04-28 16:45:101577
Fedor Indutnyce04c722014-03-13 16:38:141578 Local<Array> ary = Array::New(env->isolate());
Ben Noordhuisa7820a12013-06-04 10:21:581579 QUEUE* q = NULL;
Ben Noordhuis5f040652012-04-28 16:45:101580 int i = 0;
1581
Fedor Indutny75adde02014-02-21 13:02:421582 Local<String> owner_sym = env->owner_string();
Ben Noordhuise813e342012-05-15 15:24:061583
Fedor Indutny6a610a02014-10-04 14:44:391584 QUEUE_FOREACH(q, env->handle_wrap_queue()) {
Ben Noordhuis820aaf52014-05-27 21:31:311585 HandleWrap* w = ContainerOf(&HandleWrap::handle_wrap_queue_, q);
Fedor Indutny2bc30f22013-10-16 16:57:261586 if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
1587 continue;
Ben Noordhuis110a9cd2013-07-03 02:23:441588 Local<Object> object = w->object();
1589 Local<Value> owner = object->Get(owner_sym);
Fedor Indutny2bc30f22013-10-16 16:57:261590 if (owner->IsUndefined())
1591 owner = object;
Ben Noordhuis110a9cd2013-07-03 02:23:441592 ary->Set(i++, owner);
Ben Noordhuis5f040652012-04-28 16:45:101593 }
1594
Ben Noordhuis110a9cd2013-07-03 02:23:441595 args.GetReturnValue().Set(ary);
Ben Noordhuis5f040652012-04-28 16:45:101596}
1597
1598
Ben Noordhuis110a9cd2013-07-03 02:23:441599static void Abort(const FunctionCallbackInfo<Value>& args) {
Robert Mustacchi22404862011-12-15 01:02:151600 abort();
1601}
1602
1603
Ben Noordhuis110a9cd2013-07-03 02:23:441604static void Chdir(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421605 Environment* env = Environment::GetCurrent(args.GetIsolate());
1606 HandleScope scope(env->isolate());
Ryan Dahlb20c3432010-02-12 05:55:081607
Brandon Beacher47fcf782009-11-03 18:13:381608 if (args.Length() != 1 || !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421609 // FIXME(bnoordhuis) ThrowTypeError?
1610 return env->ThrowError("Bad argument.");
Brandon Beacher47fcf782009-11-03 18:13:381611 }
Ryan Dahlb20c3432010-02-12 05:55:081612
Timothy J Fontaine535c7772014-04-10 00:33:331613 node::Utf8Value path(args[0]);
Ben Noordhuisca9eb712013-07-18 21:18:501614 int err = uv_chdir(*path);
1615 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421616 return env->ThrowUVException(err, "uv_chdir");
Brandon Beacher47fcf782009-11-03 18:13:381617 }
Brandon Beacher47fcf782009-11-03 18:13:381618}
1619
Bert Beldercbcf4fe2011-11-24 01:19:541620
Ben Noordhuis110a9cd2013-07-03 02:23:441621static void Cwd(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421622 Environment* env = Environment::GetCurrent(args.GetIsolate());
1623 HandleScope scope(env->isolate());
Bert Beldere84edd22011-12-01 23:24:441624#ifdef _WIN32
1625 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261626 char buf[MAX_PATH * 4];
Bert Beldere84edd22011-12-01 23:24:441627#else
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261628 char buf[PATH_MAX];
Bert Beldere84edd22011-12-01 23:24:441629#endif
Michael Carter8ea6adc2009-09-01 09:39:301630
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261631 size_t cwd_len = sizeof(buf);
1632 int err = uv_cwd(buf, &cwd_len);
Ben Noordhuisca9eb712013-07-18 21:18:501633 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421634 return env->ThrowUVException(err, "uv_cwd");
Michael Carter8ea6adc2009-09-01 09:39:301635 }
Peter Griess4e3c5d82010-07-12 15:47:451636
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261637 Local<String> cwd = String::NewFromUtf8(env->isolate(),
1638 buf,
1639 String::kNormalString,
Saúl Ibarra Corretgéa0a180a2014-03-12 23:22:501640 cwd_len - 1);
Ben Noordhuis110a9cd2013-07-03 02:23:441641 args.GetReturnValue().Set(cwd);
Michael Carter8ea6adc2009-09-01 09:39:301642}
1643
Bert Beldere84edd22011-12-01 23:24:441644
Ben Noordhuis110a9cd2013-07-03 02:23:441645static void Umask(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421646 Environment* env = Environment::GetCurrent(args.GetIsolate());
1647 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:441648 uint32_t old;
isaacs5f2e9092011-01-25 18:40:121649
Ryan Dahlacc120a2011-08-09 20:53:561650 if (args.Length() < 1 || args[0]->IsUndefined()) {
Rasmus Andersson374300c2010-02-27 17:18:411651 old = umask(0);
Ben Noordhuis110a9cd2013-07-03 02:23:441652 umask(static_cast<mode_t>(old));
Fedor Indutny8e29ce92013-07-31 18:07:291653 } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421654 return env->ThrowTypeError("argument must be an integer or octal string.");
isaacs5f2e9092011-01-25 18:40:121655 } else {
1656 int oct;
Fedor Indutny8e29ce92013-07-31 18:07:291657 if (args[0]->IsInt32()) {
isaacs5f2e9092011-01-25 18:40:121658 oct = args[0]->Uint32Value();
1659 } else {
1660 oct = 0;
Timothy J Fontaine535c7772014-04-10 00:33:331661 node::Utf8Value str(args[0]);
isaacs5f2e9092011-01-25 18:40:121662
1663 // Parse the octal string.
Timothy J Fontaine1a09da62014-06-10 23:36:041664 for (size_t i = 0; i < str.length(); i++) {
isaacs5f2e9092011-01-25 18:40:121665 char c = (*str)[i];
1666 if (c > '7' || c < '0') {
Fedor Indutny75adde02014-02-21 13:02:421667 return env->ThrowTypeError("invalid octal string");
isaacs5f2e9092011-01-25 18:40:121668 }
1669 oct *= 8;
1670 oct += c - '0';
1671 }
1672 }
1673 old = umask(static_cast<mode_t>(oct));
Friedemann Altrock0433d822009-11-22 18:52:521674 }
isaacs5f2e9092011-01-25 18:40:121675
Ben Noordhuis110a9cd2013-07-03 02:23:441676 args.GetReturnValue().Set(old);
Friedemann Altrock0433d822009-11-22 18:52:521677}
1678
Michael Cartera3860762010-02-08 06:13:101679
Linus Mårtensson5e4e8ec2013-05-08 12:10:071680#if defined(__POSIX__) && !defined(__ANDROID__)
Ryan Dahlacc120a2011-08-09 20:53:561681
Ben Noordhuis3ece1302012-12-04 05:36:231682static const uid_t uid_not_found = static_cast<uid_t>(-1);
1683static const gid_t gid_not_found = static_cast<gid_t>(-1);
1684
1685
1686static uid_t uid_by_name(const char* name) {
1687 struct passwd pwd;
1688 struct passwd* pp;
1689 char buf[8192];
Ben Noordhuis3ece1302012-12-04 05:36:231690
1691 errno = 0;
1692 pp = NULL;
1693
Brian White38106da2013-04-02 16:27:191694 if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
Ben Noordhuis3ece1302012-12-04 05:36:231695 return pp->pw_uid;
1696 }
1697
1698 return uid_not_found;
1699}
1700
1701
1702static char* name_by_uid(uid_t uid) {
1703 struct passwd pwd;
1704 struct passwd* pp;
1705 char buf[8192];
1706 int rc;
1707
1708 errno = 0;
1709 pp = NULL;
1710
1711 if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1712 return strdup(pp->pw_name);
1713 }
1714
1715 if (rc == 0) {
1716 errno = ENOENT;
1717 }
1718
1719 return NULL;
1720}
1721
1722
1723static gid_t gid_by_name(const char* name) {
1724 struct group pwd;
1725 struct group* pp;
1726 char buf[8192];
Ben Noordhuis3ece1302012-12-04 05:36:231727
1728 errno = 0;
1729 pp = NULL;
1730
Brian White38106da2013-04-02 16:27:191731 if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
Ben Noordhuis3ece1302012-12-04 05:36:231732 return pp->gr_gid;
1733 }
1734
1735 return gid_not_found;
1736}
1737
1738
1739#if 0 // For future use.
1740static const char* name_by_gid(gid_t gid) {
1741 struct group pwd;
1742 struct group* pp;
1743 char buf[8192];
1744 int rc;
1745
1746 errno = 0;
1747 pp = NULL;
1748
1749 if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1750 return strdup(pp->gr_name);
1751 }
1752
1753 if (rc == 0) {
1754 errno = ENOENT;
1755 }
1756
1757 return NULL;
1758}
1759#endif
1760
1761
1762static uid_t uid_by_name(Handle<Value> value) {
1763 if (value->IsUint32()) {
1764 return static_cast<uid_t>(value->Uint32Value());
1765 } else {
Timothy J Fontaine535c7772014-04-10 00:33:331766 node::Utf8Value name(value);
Ben Noordhuis3ece1302012-12-04 05:36:231767 return uid_by_name(*name);
1768 }
1769}
1770
1771
1772static gid_t gid_by_name(Handle<Value> value) {
1773 if (value->IsUint32()) {
1774 return static_cast<gid_t>(value->Uint32Value());
1775 } else {
Timothy J Fontaine535c7772014-04-10 00:33:331776 node::Utf8Value name(value);
Ben Noordhuis3ece1302012-12-04 05:36:231777 return gid_by_name(*name);
1778 }
1779}
1780
1781
Ben Noordhuis110a9cd2013-07-03 02:23:441782static void GetUid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis6df47412013-09-05 19:47:081783 // uid_t is an uint32_t on all supported platforms.
1784 args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
Michael Cartera3860762010-02-08 06:13:101785}
1786
Ryan Dahlacc120a2011-08-09 20:53:561787
Ben Noordhuis110a9cd2013-07-03 02:23:441788static void GetGid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis6df47412013-09-05 19:47:081789 // gid_t is an uint32_t on all supported platforms.
1790 args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
James Duncandf1c1e52010-02-23 22:45:021791}
1792
1793
Ben Noordhuis110a9cd2013-07-03 02:23:441794static void SetGid(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421795 Environment* env = Environment::GetCurrent(args.GetIsolate());
1796 HandleScope scope(env->isolate());
Ryan Dahl39943402010-03-15 19:49:401797
Ben Noordhuis3ece1302012-12-04 05:36:231798 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421799 return env->ThrowTypeError("setgid argument must be a number or a string");
James Duncandf1c1e52010-02-23 22:45:021800 }
1801
Ben Noordhuis3ece1302012-12-04 05:36:231802 gid_t gid = gid_by_name(args[0]);
Blake Mizerany8c853402010-06-30 06:12:461803
Ben Noordhuis3ece1302012-12-04 05:36:231804 if (gid == gid_not_found) {
Fedor Indutny75adde02014-02-21 13:02:421805 return env->ThrowError("setgid group id does not exist");
Peter Griess2420f072010-05-19 00:40:441806 }
1807
Ben Noordhuis3ece1302012-12-04 05:36:231808 if (setgid(gid)) {
Fedor Indutny75adde02014-02-21 13:02:421809 return env->ThrowErrnoException(errno, "setgid");
James Duncandf1c1e52010-02-23 22:45:021810 }
James Duncandf1c1e52010-02-23 22:45:021811}
Michael Cartera3860762010-02-08 06:13:101812
Ryan Dahlacc120a2011-08-09 20:53:561813
Ben Noordhuis110a9cd2013-07-03 02:23:441814static void SetUid(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421815 Environment* env = Environment::GetCurrent(args.GetIsolate());
1816 HandleScope scope(env->isolate());
Michael Cartera3860762010-02-08 06:13:101817
Ben Noordhuis3ece1302012-12-04 05:36:231818 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421819 return env->ThrowTypeError("setuid argument must be a number or a string");
Michael Cartera3860762010-02-08 06:13:101820 }
1821
Ben Noordhuis3ece1302012-12-04 05:36:231822 uid_t uid = uid_by_name(args[0]);
Peter Griess2420f072010-05-19 00:40:441823
Ben Noordhuis3ece1302012-12-04 05:36:231824 if (uid == uid_not_found) {
Fedor Indutny75adde02014-02-21 13:02:421825 return env->ThrowError("setuid user id does not exist");
Peter Griess2420f072010-05-19 00:40:441826 }
1827
Ben Noordhuis3ece1302012-12-04 05:36:231828 if (setuid(uid)) {
Fedor Indutny75adde02014-02-21 13:02:421829 return env->ThrowErrnoException(errno, "setuid");
Michael Cartera3860762010-02-08 06:13:101830 }
Michael Cartera3860762010-02-08 06:13:101831}
1832
Ryan Dahlacc120a2011-08-09 20:53:561833
Ben Noordhuis110a9cd2013-07-03 02:23:441834static void GetGroups(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421835 Environment* env = Environment::GetCurrent(args.GetIsolate());
1836 HandleScope scope(env->isolate());
Ben Noordhuis3ece1302012-12-04 05:36:231837
1838 int ngroups = getgroups(0, NULL);
1839
1840 if (ngroups == -1) {
Fedor Indutny75adde02014-02-21 13:02:421841 return env->ThrowErrnoException(errno, "getgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231842 }
1843
1844 gid_t* groups = new gid_t[ngroups];
1845
1846 ngroups = getgroups(ngroups, groups);
1847
1848 if (ngroups == -1) {
1849 delete[] groups;
Fedor Indutny75adde02014-02-21 13:02:421850 return env->ThrowErrnoException(errno, "getgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231851 }
1852
Fedor Indutnyce04c722014-03-13 16:38:141853 Local<Array> groups_list = Array::New(env->isolate(), ngroups);
Ben Noordhuis3ece1302012-12-04 05:36:231854 bool seen_egid = false;
1855 gid_t egid = getegid();
1856
1857 for (int i = 0; i < ngroups; i++) {
Fedor Indutnyce04c722014-03-13 16:38:141858 groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
Fedor Indutny2bc30f22013-10-16 16:57:261859 if (groups[i] == egid)
1860 seen_egid = true;
Ben Noordhuis3ece1302012-12-04 05:36:231861 }
1862
1863 delete[] groups;
1864
1865 if (seen_egid == false) {
Fedor Indutnyce04c722014-03-13 16:38:141866 groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
Ben Noordhuis3ece1302012-12-04 05:36:231867 }
1868
Ben Noordhuis110a9cd2013-07-03 02:23:441869 args.GetReturnValue().Set(groups_list);
Ben Noordhuis3ece1302012-12-04 05:36:231870}
1871
1872
Ben Noordhuis110a9cd2013-07-03 02:23:441873static void SetGroups(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421874 Environment* env = Environment::GetCurrent(args.GetIsolate());
1875 HandleScope scope(env->isolate());
Ben Noordhuis3ece1302012-12-04 05:36:231876
1877 if (!args[0]->IsArray()) {
Fedor Indutny75adde02014-02-21 13:02:421878 return env->ThrowTypeError("argument 1 must be an array");
Ben Noordhuis3ece1302012-12-04 05:36:231879 }
1880
1881 Local<Array> groups_list = args[0].As<Array>();
1882 size_t size = groups_list->Length();
1883 gid_t* groups = new gid_t[size];
1884
1885 for (size_t i = 0; i < size; i++) {
1886 gid_t gid = gid_by_name(groups_list->Get(i));
1887
1888 if (gid == gid_not_found) {
1889 delete[] groups;
Fedor Indutny75adde02014-02-21 13:02:421890 return env->ThrowError("group name not found");
Ben Noordhuis3ece1302012-12-04 05:36:231891 }
1892
1893 groups[i] = gid;
1894 }
1895
1896 int rc = setgroups(size, groups);
1897 delete[] groups;
1898
1899 if (rc == -1) {
Fedor Indutny75adde02014-02-21 13:02:421900 return env->ThrowErrnoException(errno, "setgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231901 }
Ben Noordhuis3ece1302012-12-04 05:36:231902}
1903
1904
Ben Noordhuis110a9cd2013-07-03 02:23:441905static void InitGroups(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421906 Environment* env = Environment::GetCurrent(args.GetIsolate());
1907 HandleScope scope(env->isolate());
Ben Noordhuis3ece1302012-12-04 05:36:231908
1909 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421910 return env->ThrowTypeError("argument 1 must be a number or a string");
Ben Noordhuis3ece1302012-12-04 05:36:231911 }
1912
1913 if (!args[1]->IsUint32() && !args[1]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421914 return env->ThrowTypeError("argument 2 must be a number or a string");
Ben Noordhuis3ece1302012-12-04 05:36:231915 }
1916
Timothy J Fontaine535c7772014-04-10 00:33:331917 node::Utf8Value arg0(args[0]);
Ben Noordhuis3ece1302012-12-04 05:36:231918 gid_t extra_group;
1919 bool must_free;
1920 char* user;
1921
1922 if (args[0]->IsUint32()) {
1923 user = name_by_uid(args[0]->Uint32Value());
1924 must_free = true;
1925 } else {
1926 user = *arg0;
1927 must_free = false;
1928 }
1929
1930 if (user == NULL) {
Fedor Indutny75adde02014-02-21 13:02:421931 return env->ThrowError("initgroups user not found");
Ben Noordhuis3ece1302012-12-04 05:36:231932 }
1933
1934 extra_group = gid_by_name(args[1]);
1935
1936 if (extra_group == gid_not_found) {
Fedor Indutny2bc30f22013-10-16 16:57:261937 if (must_free)
1938 free(user);
Fedor Indutny75adde02014-02-21 13:02:421939 return env->ThrowError("initgroups extra group not found");
Ben Noordhuis3ece1302012-12-04 05:36:231940 }
1941
1942 int rc = initgroups(user, extra_group);
1943
1944 if (must_free) {
1945 free(user);
1946 }
1947
1948 if (rc) {
Fedor Indutny75adde02014-02-21 13:02:421949 return env->ThrowErrnoException(errno, "initgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231950 }
Ben Noordhuis3ece1302012-12-04 05:36:231951}
1952
Fedor Indutny8e29ce92013-07-31 18:07:291953#endif // __POSIX__ && !defined(__ANDROID__)
Bert Belder30bab522010-11-25 00:09:061954
Michael Cartera3860762010-02-08 06:13:101955
Ben Noordhuis110a9cd2013-07-03 02:23:441956void Exit(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421957 Environment* env = Environment::GetCurrent(args.GetIsolate());
1958 HandleScope scope(env->isolate());
Rasmus Christian Pedersen734fb492014-09-18 12:10:531959 exit(args[0]->Int32Value());
Ryan0f517032009-04-29 09:09:321960}
1961
Ryan Dahl3ac6dee2010-05-08 02:05:591962
Ben Noordhuis110a9cd2013-07-03 02:23:441963static void Uptime(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:421964 Environment* env = Environment::GetCurrent(args.GetIsolate());
1965 HandleScope scope(env->isolate());
Igor Zinkovsky500c8f42011-12-15 20:36:051966 double uptime;
Tom Hughescf78ce52011-03-04 23:57:541967
Fedor Indutny6a610a02014-10-04 14:44:391968 uv_update_time(env->event_loop());
1969 uptime = uv_now(env->event_loop()) - prog_start_time;
Tom Hughescf78ce52011-03-04 23:57:541970
Timothy J Fontaineb19b60a2014-05-01 20:54:231971 args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
Tom Hughescf78ce52011-03-04 23:57:541972}
Ryan Dahl3ac6dee2010-05-08 02:05:591973
Ryan Dahlc344fbc2011-10-06 21:59:381974
Ben Noordhuis110a9cd2013-07-03 02:23:441975void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis09724b32013-11-11 21:02:031976 Environment* env = Environment::GetCurrent(args.GetIsolate());
Fedor Indutny75adde02014-02-21 13:02:421977 HandleScope scope(env->isolate());
Ryan Dahlb3b3cfe2009-11-03 12:00:421978
Ryan Dahl5783a522011-10-18 21:30:311979 size_t rss;
Ben Noordhuisca9eb712013-07-18 21:18:501980 int err = uv_resident_set_memory(&rss);
1981 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421982 return env->ThrowUVException(err, "uv_resident_set_memory");
Ryan Dahl3a701292009-11-03 00:30:011983 }
1984
Ryan Dahl38e425d2009-11-28 15:31:291985 // V8 memory usage
1986 HeapStatistics v8_heap_stats;
Fedor Indutny75adde02014-02-21 13:02:421987 env->isolate()->GetHeapStatistics(&v8_heap_stats);
Ben Noordhuis756b6222013-08-10 22:26:111988
1989 Local<Integer> heap_total =
Fedor Indutnyce04c722014-03-13 16:38:141990 Integer::NewFromUnsigned(env->isolate(), v8_heap_stats.total_heap_size());
Ben Noordhuis756b6222013-08-10 22:26:111991 Local<Integer> heap_used =
Fedor Indutnyce04c722014-03-13 16:38:141992 Integer::NewFromUnsigned(env->isolate(), v8_heap_stats.used_heap_size());
Ben Noordhuis756b6222013-08-10 22:26:111993
Fedor Indutnyce04c722014-03-13 16:38:141994 Local<Object> info = Object::New(env->isolate());
Fedor Indutny75adde02014-02-21 13:02:421995 info->Set(env->rss_string(), Number::New(env->isolate(), rss));
Ben Noordhuis756b6222013-08-10 22:26:111996 info->Set(env->heap_total_string(), heap_total);
1997 info->Set(env->heap_used_string(), heap_used);
Ryan Dahl38e425d2009-11-28 15:31:291998
Ben Noordhuis110a9cd2013-07-03 02:23:441999 args.GetReturnValue().Set(info);
Ryan Dahl3a701292009-11-03 00:30:012000}
Ryan Dahlb3b3cfe2009-11-03 12:00:422001
Bert Belder4a2cb072010-11-29 17:40:142002
Ben Noordhuis110a9cd2013-07-03 02:23:442003void Kill(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:422004 Environment* env = Environment::GetCurrent(args.GetIsolate());
2005 HandleScope scope(env->isolate());
Ryan Dahlb20c3432010-02-12 05:55:082006
Ryan Dahl4227e9d2010-12-21 23:40:102007 if (args.Length() != 2) {
Fedor Indutny75adde02014-02-21 13:02:422008 return env->ThrowError("Bad argument.");
Brandon Beacher334d56d2009-10-14 21:56:122009 }
Ryan Dahlb20c3432010-02-12 05:55:082010
Rasmus Christian Pedersen734fb492014-09-18 12:10:532011 int pid = args[0]->Int32Value();
Ryan Dahl6eca9482010-09-17 06:13:032012 int sig = args[1]->Int32Value();
Ben Noordhuisca9eb712013-07-18 21:18:502013 int err = uv_kill(pid, sig);
2014 args.GetReturnValue().Set(err);
Brandon Beacher334d56d2009-10-14 21:56:122015}
2016
Nathan Rajlich07c886f2012-03-05 16:51:582017// used in Hrtime() below
2018#define NANOS_PER_SEC 1000000000
2019
2020// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
2021// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2022// so this function instead returns an Array with 2 entries representing seconds
2023// and nanoseconds, to avoid any integer overflow possibility.
2024// Pass in an Array from a previous hrtime() call to instead get a time diff.
Ben Noordhuis110a9cd2013-07-03 02:23:442025void Hrtime(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:422026 Environment* env = Environment::GetCurrent(args.GetIsolate());
2027 HandleScope scope(env->isolate());
Nathan Rajlich07c886f2012-03-05 16:51:582028
2029 uint64_t t = uv_hrtime();
2030
2031 if (args.Length() > 0) {
2032 // return a time diff tuple
Nathan Rajlichd3d83d72012-07-08 02:57:022033 if (!args[0]->IsArray()) {
Fedor Indutny75adde02014-02-21 13:02:422034 return env->ThrowTypeError(
2035 "process.hrtime() only accepts an Array tuple.");
Nathan Rajlichd3d83d72012-07-08 02:57:022036 }
Nathan Rajlich07c886f2012-03-05 16:51:582037 Local<Array> inArray = Local<Array>::Cast(args[0]);
2038 uint64_t seconds = inArray->Get(0)->Uint32Value();
2039 uint64_t nanos = inArray->Get(1)->Uint32Value();
2040 t -= (seconds * NANOS_PER_SEC) + nanos;
2041 }
2042
Fedor Indutnyce04c722014-03-13 16:38:142043 Local<Array> tuple = Array::New(env->isolate(), 2);
2044 tuple->Set(0, Integer::NewFromUnsigned(env->isolate(), t / NANOS_PER_SEC));
2045 tuple->Set(1, Integer::NewFromUnsigned(env->isolate(), t % NANOS_PER_SEC));
Ben Noordhuis110a9cd2013-07-03 02:23:442046 args.GetReturnValue().Set(tuple);
Nathan Rajlich07c886f2012-03-05 16:51:582047}
2048
Keith M Wesolowski76b98462013-12-17 00:00:442049extern "C" void node_module_register(void* m) {
2050 struct node_module* mp = reinterpret_cast<struct node_module*>(m);
2051
2052 if (mp->nm_flags & NM_F_BUILTIN) {
2053 mp->nm_link = modlist_builtin;
2054 modlist_builtin = mp;
2055 } else {
2056 assert(modpending == NULL);
2057 modpending = mp;
2058 }
2059}
2060
2061struct node_module* get_builtin_module(const char* name) {
2062 struct node_module* mp;
2063
2064 for (mp = modlist_builtin; mp != NULL; mp = mp->nm_link) {
2065 if (strcmp(mp->nm_modname, name) == 0)
2066 break;
2067 }
2068
2069 assert(mp == NULL || (mp->nm_flags & NM_F_BUILTIN) != 0);
2070 return (mp);
2071}
Bert Belderdd93c532011-10-28 10:05:092072
2073typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
Ryan2b6d7242009-06-20 13:07:102074
isaacs15508582013-01-24 23:40:582075// DLOpen is process.dlopen(module, filename).
2076// Used to load 'module.node' dynamically shared objects.
Ben Noordhuis756b6222013-08-10 22:26:112077//
2078// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2079// when two contexts try to load the same shared object. Maybe have a shadow
2080// cache that's a plain C list or hash table that's shared across contexts?
Ben Noordhuis110a9cd2013-07-03 02:23:442081void DLOpen(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis756b6222013-08-10 22:26:112082 HandleScope handle_scope(args.GetIsolate());
Ben Noordhuis09724b32013-11-11 21:02:032083 Environment* env = Environment::GetCurrent(args.GetIsolate());
Keith M Wesolowski76b98462013-12-17 00:00:442084 struct node_module* mp;
Bert Belderdd93c532011-10-28 10:05:092085 uv_lib_t lib;
Ryan2b6d7242009-06-20 13:07:102086
Bert Belderdd93c532011-10-28 10:05:092087 if (args.Length() < 2) {
Fedor Indutny75adde02014-02-21 13:02:422088 env->ThrowError("process.dlopen takes exactly 2 arguments.");
Keith M Wesolowski76b98462013-12-17 00:00:442089 return;
Bert Belderdd93c532011-10-28 10:05:092090 }
Ryana97dce72009-08-31 09:14:342091
Fedor Indutny8e29ce92013-07-31 18:07:292092 Local<Object> module = args[0]->ToObject(); // Cast
Timothy J Fontaine1a09da62014-06-10 23:36:042093 node::Utf8Value filename(args[1]); // Cast
isaacs15508582013-01-24 23:40:582094
Ben Noordhuis756b6222013-08-10 22:26:112095 Local<String> exports_string = env->exports_string();
2096 Local<Object> exports = module->Get(exports_string)->ToObject();
Ryan2b6d7242009-06-20 13:07:102097
Ben Noordhuis039fac62012-05-17 05:13:292098 if (uv_dlopen(*filename, &lib)) {
Ben Noordhuis756b6222013-08-10 22:26:112099 Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
Ben Noordhuis039fac62012-05-17 05:13:292100#ifdef _WIN32
2101 // Windows needs to add the filename into the error message
isaacs6076a252013-03-07 23:14:222102 errmsg = String::Concat(errmsg, args[1]->ToString());
Fedor Indutny8e29ce92013-07-31 18:07:292103#endif // _WIN32
Fedor Indutny75adde02014-02-21 13:02:422104 env->isolate()->ThrowException(Exception::Error(errmsg));
Ben Noordhuis110a9cd2013-07-03 02:23:442105 return;
Ryan2b6d7242009-06-20 13:07:102106 }
2107
Keith M Wesolowski76b98462013-12-17 00:00:442108 /*
2109 * Objects containing v14 or later modules will have registered themselves
2110 * on the pending list. Activate all of them now. At present, only one
2111 * module per object is supported.
Ben Noordhuis8ccfed22012-12-18 08:56:572112 */
Keith M Wesolowski76b98462013-12-17 00:00:442113 mp = modpending;
2114 modpending = NULL;
Ben Noordhuis8ccfed22012-12-18 08:56:572115
Keith M Wesolowski76b98462013-12-17 00:00:442116 if (mp == NULL) {
Fedor Indutny75adde02014-02-21 13:02:422117 env->ThrowError("Module did not self-register.");
Keith M Wesolowski76b98462013-12-17 00:00:442118 return;
Paul Querna367b87d2010-07-13 08:33:512119 }
Keith M Wesolowski76b98462013-12-17 00:00:442120 if (mp->nm_version != NODE_MODULE_VERSION) {
Ben Noordhuisf6923472012-07-26 23:06:122121 char errmsg[1024];
2122 snprintf(errmsg,
2123 sizeof(errmsg),
2124 "Module version mismatch. Expected %d, got %d.",
Keith M Wesolowski76b98462013-12-17 00:00:442125 NODE_MODULE_VERSION, mp->nm_version);
Fedor Indutny75adde02014-02-21 13:02:422126 env->ThrowError(errmsg);
Keith M Wesolowski76b98462013-12-17 00:00:442127 return;
2128 }
2129 if (mp->nm_flags & NM_F_BUILTIN) {
Fedor Indutny75adde02014-02-21 13:02:422130 env->ThrowError("Built-in module self-registered.");
Keith M Wesolowski76b98462013-12-17 00:00:442131 return;
Ryan2b6d7242009-06-20 13:07:102132 }
Ryan2b6d7242009-06-20 13:07:102133
Keith M Wesolowski76b98462013-12-17 00:00:442134 mp->nm_dso_handle = lib.handle;
2135 mp->nm_link = modlist_addon;
2136 modlist_addon = mp;
2137
2138 if (mp->nm_context_register_func != NULL) {
2139 mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2140 } else if (mp->nm_register_func != NULL) {
2141 mp->nm_register_func(exports, module, mp->nm_priv);
Ben Noordhuis756b6222013-08-10 22:26:112142 } else {
Fedor Indutny75adde02014-02-21 13:02:422143 env->ThrowError("Module has no declared entry point.");
Keith M Wesolowski76b98462013-12-17 00:00:442144 return;
Ben Noordhuis756b6222013-08-10 22:26:112145 }
Ryan2b6d7242009-06-20 13:07:102146
Peter Griess4e3c5d82010-07-12 15:47:452147 // Tell coverity that 'handle' should not be freed when we return.
2148 // coverity[leaked_storage]
Ryan2b6d7242009-06-20 13:07:102149}
2150
Tim-Smartae10a482010-03-12 08:36:002151
Ryand6c9d312009-09-11 14:02:292152static void OnFatalError(const char* location, const char* message) {
Ryan Dahl53a841d2009-12-29 19:20:512153 if (location) {
2154 fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
2155 } else {
2156 fprintf(stderr, "FATAL ERROR: %s\n", message);
2157 }
Ben Noordhuisc56a96c2013-06-29 05:30:112158 fflush(stderr);
Ben Noordhuisc56a96c2013-06-29 05:30:112159 abort();
Ryan63a9cd32009-04-15 08:08:282160}
2161
Miroslav Bajtosc16963b2013-06-17 19:19:592162
Trevor Norrisfa10b752013-06-20 23:44:022163NO_RETURN void FatalError(const char* location, const char* message) {
2164 OnFatalError(location, message);
2165 // to supress compiler warning
2166 abort();
2167}
2168
2169
Fedor Indutny75adde02014-02-21 13:02:422170void FatalException(Isolate* isolate,
2171 Handle<Value> error,
2172 Handle<Message> message) {
2173 HandleScope scope(isolate);
Felix Geisendörfer2b252ac2009-11-14 22:07:542174
Fedor Indutny75adde02014-02-21 13:02:422175 Environment* env = Environment::GetCurrent(isolate);
Ben Noordhuis756b6222013-08-10 22:26:112176 Local<Object> process_object = env->process_object();
2177 Local<String> fatal_exception_string = env->fatal_exception_string();
2178 Local<Function> fatal_exception_function =
2179 process_object->Get(fatal_exception_string).As<Function>();
Ryan Dahl45a806a2009-12-09 08:02:212180
Ben Noordhuis756b6222013-08-10 22:26:112181 if (!fatal_exception_function->IsFunction()) {
isaacs4401bb42012-12-26 20:28:332182 // failed before the process._fatalException function was added!
2183 // this is probably pretty bad. Nothing to do but report and exit.
Fedor Indutnyf1de13b2014-02-05 16:38:332184 ReportException(env, error, message);
isaacs95862b22013-02-27 19:23:202185 exit(6);
Felix Geisendörfer2b252ac2009-11-14 22:07:542186 }
2187
isaacs4401bb42012-12-26 20:28:332188 TryCatch fatal_try_catch;
isaacs07be9fc2012-05-09 22:12:132189
Miroslav Bajtosc16963b2013-06-17 19:19:592190 // Do not call FatalException when _fatalException handler throws
2191 fatal_try_catch.SetVerbose(false);
2192
isaacs4401bb42012-12-26 20:28:332193 // this will return true if the JS layer handled it, false otherwise
Ben Noordhuis756b6222013-08-10 22:26:112194 Local<Value> caught =
2195 fatal_exception_function->Call(process_object, 1, &error);
isaacs4401bb42012-12-26 20:28:332196
2197 if (fatal_try_catch.HasCaught()) {
2198 // the fatal exception function threw, so we must exit
Fedor Indutnyf1de13b2014-02-05 16:38:332199 ReportException(env, fatal_try_catch);
isaacs95862b22013-02-27 19:23:202200 exit(7);
isaacs4401bb42012-12-26 20:28:332201 }
2202
2203 if (false == caught->BooleanValue()) {
Fedor Indutnyf1de13b2014-02-05 16:38:332204 ReportException(env, error, message);
isaacsb30a03e2013-09-07 00:47:562205 exit(1);
isaacs80a55e92012-04-07 02:23:162206 }
Ryane78917b2009-03-09 13:08:312207}
2208
Ryan0e9e9272009-04-04 14:53:432209
Fedor Indutny75adde02014-02-21 13:02:422210void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2211 HandleScope scope(isolate);
Fedor Indutny8e29ce92013-07-31 18:07:292212 // TODO(bajtos) do not call FatalException if try_catch is verbose
Miroslav Bajtosc16963b2013-06-17 19:19:592213 // (requires V8 API to expose getter for try_catch.is_verbose_)
Fedor Indutny75adde02014-02-21 13:02:422214 FatalException(isolate, try_catch.Exception(), try_catch.Message());
Miroslav Bajtosc16963b2013-06-17 19:19:592215}
2216
2217
2218void OnMessage(Handle<Message> message, Handle<Value> error) {
2219 // The current version of V8 sends messages for errors only
2220 // (thus `error` is always set).
Fedor Indutny75adde02014-02-21 13:02:422221 FatalException(Isolate::GetCurrent(), error, message);
Miroslav Bajtosc16963b2013-06-17 19:19:592222}
2223
2224
Ben Noordhuis110a9cd2013-07-03 02:23:442225static void Binding(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis756b6222013-08-10 22:26:112226 HandleScope handle_scope(args.GetIsolate());
Ben Noordhuis09724b32013-11-11 21:02:032227 Environment* env = Environment::GetCurrent(args.GetIsolate());
Ryan Dahl627fb5a2010-03-15 20:48:032228
2229 Local<String> module = args[0]->ToString();
Timothy J Fontaine535c7772014-04-10 00:33:332230 node::Utf8Value module_v(module);
Ryan Dahl627fb5a2010-03-15 20:48:032231
Ben Noordhuis756b6222013-08-10 22:26:112232 Local<Object> cache = env->binding_cache_object();
Ryan Dahl627fb5a2010-03-15 20:48:032233 Local<Object> exports;
2234
Ben Noordhuis110a9cd2013-07-03 02:23:442235 if (cache->Has(module)) {
2236 exports = cache->Get(module)->ToObject();
2237 args.GetReturnValue().Set(exports);
2238 return;
Ryan Dahlea9ee1f2011-07-28 02:30:322239 }
Ryan Dahl6eca9482010-09-17 06:13:032240
Ryan Dahlea9ee1f2011-07-28 02:30:322241 // Append a string to process.moduleLoadList
2242 char buf[1024];
Fedor Indutny8e29ce92013-07-31 18:07:292243 snprintf(buf, sizeof(buf), "Binding %s", *module_v);
Ben Noordhuis110a9cd2013-07-03 02:23:442244
Ben Noordhuis756b6222013-08-10 22:26:112245 Local<Array> modules = env->module_load_list_array();
Ben Noordhuis110a9cd2013-07-03 02:23:442246 uint32_t l = modules->Length();
Fedor Indutny75adde02014-02-21 13:02:422247 modules->Set(l, OneByteString(env->isolate(), buf));
Ryan Dahlea9ee1f2011-07-28 02:30:322248
Keith M Wesolowski76b98462013-12-17 00:00:442249 node_module* mod = get_builtin_module(*module_v);
Ben Noordhuis756b6222013-08-10 22:26:112250 if (mod != NULL) {
Fedor Indutnyce04c722014-03-13 16:38:142251 exports = Object::New(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:112252 // Internal bindings don't have a "module" object, only exports.
Keith M Wesolowski76b98462013-12-17 00:00:442253 assert(mod->nm_register_func == NULL);
2254 assert(mod->nm_context_register_func != NULL);
Ben Noordhuis756b6222013-08-10 22:26:112255 Local<Value> unused = Undefined(env->isolate());
Keith M Wesolowski76b98462013-12-17 00:00:442256 mod->nm_context_register_func(exports, unused,
2257 env->context(), mod->nm_priv);
Ben Noordhuis110a9cd2013-07-03 02:23:442258 cache->Set(module, exports);
Ryan Dahl6eca9482010-09-17 06:13:032259 } else if (!strcmp(*module_v, "constants")) {
Fedor Indutnyce04c722014-03-13 16:38:142260 exports = Object::New(env->isolate());
Ryan Dahl6eca9482010-09-17 06:13:032261 DefineConstants(exports);
Ben Noordhuis110a9cd2013-07-03 02:23:442262 cache->Set(module, exports);
Ryan Dahlc90546f2010-03-15 21:22:502263 } else if (!strcmp(*module_v, "natives")) {
Fedor Indutnyce04c722014-03-13 16:38:142264 exports = Object::New(env->isolate());
Fedor Indutny75adde02014-02-21 13:02:422265 DefineJavaScript(env, exports);
Ben Noordhuis110a9cd2013-07-03 02:23:442266 cache->Set(module, exports);
Ryan Dahl627fb5a2010-03-15 20:48:032267 } else {
Jackson Tian962e6512014-08-01 11:26:092268 char errmsg[1024];
2269 snprintf(errmsg,
2270 sizeof(errmsg),
2271 "No such module: %s",
2272 *module_v);
2273 return env->ThrowError(errmsg);
Ryan Dahl627fb5a2010-03-15 20:48:032274 }
2275
Ben Noordhuis110a9cd2013-07-03 02:23:442276 args.GetReturnValue().Set(exports);
Ryan Dahl627fb5a2010-03-15 20:48:032277}
2278
Ryan Dahle742d072009-10-09 11:25:042279
Ben Noordhuis110a9cd2013-07-03 02:23:442280static void ProcessTitleGetter(Local<String> property,
2281 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422282 Environment* env = Environment::GetCurrent(info.GetIsolate());
2283 HandleScope scope(env->isolate());
Igor Zinkovsky500c8f42011-12-15 20:36:052284 char buffer[512];
2285 uv_get_process_title(buffer, sizeof(buffer));
Fedor Indutny75adde02014-02-21 13:02:422286 info.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), buffer));
Ryan Dahl5185c152010-06-18 07:26:492287}
2288
2289
2290static void ProcessTitleSetter(Local<String> property,
2291 Local<Value> value,
Ben Noordhuis110a9cd2013-07-03 02:23:442292 const PropertyCallbackInfo<void>& info) {
Fedor Indutny75adde02014-02-21 13:02:422293 Environment* env = Environment::GetCurrent(info.GetIsolate());
2294 HandleScope scope(env->isolate());
Timothy J Fontaine535c7772014-04-10 00:33:332295 node::Utf8Value title(value);
Fedor Indutny8e29ce92013-07-31 18:07:292296 // TODO(piscisaureus): protect with a lock
Igor Zinkovsky500c8f42011-12-15 20:36:052297 uv_set_process_title(*title);
Ryan Dahl5185c152010-06-18 07:26:492298}
2299
2300
Ben Noordhuis110a9cd2013-07-03 02:23:442301static void EnvGetter(Local<String> property,
2302 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422303 Environment* env = Environment::GetCurrent(info.GetIsolate());
2304 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182305#ifdef __POSIX__
Timothy J Fontaine535c7772014-04-10 00:33:332306 node::Utf8Value key(property);
Ben Noordhuisb4def482010-10-15 13:48:342307 const char* val = getenv(*key);
2308 if (val) {
Fedor Indutny75adde02014-02-21 13:02:422309 return info.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), val));
Ben Noordhuisb4def482010-10-15 13:48:342310 }
Bert Belder077f9d72012-02-15 22:34:182311#else // _WIN32
2312 String::Value key(property);
Fedor Indutny8e29ce92013-07-31 18:07:292313 WCHAR buffer[32767]; // The maximum size allowed for environment variables.
Bert Belder077f9d72012-02-15 22:34:182314 DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2315 buffer,
2316 ARRAY_SIZE(buffer));
2317 // If result >= sizeof buffer the buffer was too small. That should never
2318 // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2319 // not found.
2320 if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2321 result < ARRAY_SIZE(buffer)) {
Ben Noordhuisf674b092013-08-07 19:50:412322 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
Fedor Indutny75adde02014-02-21 13:02:422323 Local<String> rc = String::NewFromTwoByte(env->isolate(), two_byte_buffer);
Ben Noordhuisf674b092013-08-07 19:50:412324 return info.GetReturnValue().Set(rc);
Bert Belder077f9d72012-02-15 22:34:182325 }
2326#endif
Ben Noordhuisfee02db2012-06-29 15:29:322327 // Not found. Fetch from prototype.
Ben Noordhuis110a9cd2013-07-03 02:23:442328 info.GetReturnValue().Set(
2329 info.Data().As<Object>()->Get(property));
Ben Noordhuisb4def482010-10-15 13:48:342330}
2331
2332
Ben Noordhuis110a9cd2013-07-03 02:23:442333static void EnvSetter(Local<String> property,
2334 Local<Value> value,
2335 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422336 Environment* env = Environment::GetCurrent(info.GetIsolate());
2337 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182338#ifdef __POSIX__
Timothy J Fontaine535c7772014-04-10 00:33:332339 node::Utf8Value key(property);
2340 node::Utf8Value val(value);
Ben Noordhuisb4def482010-10-15 13:48:342341 setenv(*key, *val, 1);
Bert Belder077f9d72012-02-15 22:34:182342#else // _WIN32
2343 String::Value key(property);
2344 String::Value val(value);
2345 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2346 // Environment variables that start with '=' are read-only.
2347 if (key_ptr[0] != L'=') {
2348 SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
Ryan Dahle6b06bc2011-08-11 00:14:232349 }
Bert Belder30bab522010-11-25 00:09:062350#endif
Bert Belder077f9d72012-02-15 22:34:182351 // Whether it worked or not, always return rval.
Ben Noordhuis110a9cd2013-07-03 02:23:442352 info.GetReturnValue().Set(value);
Ben Noordhuisb4def482010-10-15 13:48:342353}
2354
2355
Ben Noordhuis110a9cd2013-07-03 02:23:442356static void EnvQuery(Local<String> property,
2357 const PropertyCallbackInfo<Integer>& info) {
Fedor Indutny75adde02014-02-21 13:02:422358 Environment* env = Environment::GetCurrent(info.GetIsolate());
2359 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442360 int32_t rc = -1; // Not found unless proven otherwise.
Bert Belder077f9d72012-02-15 22:34:182361#ifdef __POSIX__
Timothy J Fontaine535c7772014-04-10 00:33:332362 node::Utf8Value key(property);
Fedor Indutny2bc30f22013-10-16 16:57:262363 if (getenv(*key))
2364 rc = 0;
Bert Belder077f9d72012-02-15 22:34:182365#else // _WIN32
2366 String::Value key(property);
2367 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2368 if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
2369 GetLastError() == ERROR_SUCCESS) {
Ben Noordhuis110a9cd2013-07-03 02:23:442370 rc = 0;
Bert Belder077f9d72012-02-15 22:34:182371 if (key_ptr[0] == L'=') {
2372 // Environment variables that start with '=' are hidden and read-only.
Ben Noordhuis110a9cd2013-07-03 02:23:442373 rc = static_cast<int32_t>(v8::ReadOnly) |
2374 static_cast<int32_t>(v8::DontDelete) |
2375 static_cast<int32_t>(v8::DontEnum);
Bert Belder077f9d72012-02-15 22:34:182376 }
2377 }
2378#endif
Fedor Indutny2bc30f22013-10-16 16:57:262379 if (rc != -1)
2380 info.GetReturnValue().Set(rc);
Ben Noordhuisb4def482010-10-15 13:48:342381}
2382
2383
Ben Noordhuis110a9cd2013-07-03 02:23:442384static void EnvDeleter(Local<String> property,
2385 const PropertyCallbackInfo<Boolean>& info) {
Fedor Indutny75adde02014-02-21 13:02:422386 Environment* env = Environment::GetCurrent(info.GetIsolate());
2387 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442388 bool rc = true;
Bert Belder30bab522010-11-25 00:09:062389#ifdef __POSIX__
Timothy J Fontaine535c7772014-04-10 00:33:332390 node::Utf8Value key(property);
Ben Noordhuis110a9cd2013-07-03 02:23:442391 rc = getenv(*key) != NULL;
Fedor Indutny2bc30f22013-10-16 16:57:262392 if (rc)
2393 unsetenv(*key);
Bert Belder30bab522010-11-25 00:09:062394#else
Bert Belder077f9d72012-02-15 22:34:182395 String::Value key(property);
2396 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2397 if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
2398 // Deletion failed. Return true if the key wasn't there in the first place,
2399 // false if it is still there.
Ben Noordhuis110a9cd2013-07-03 02:23:442400 rc = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
2401 GetLastError() != ERROR_SUCCESS;
Ben Noordhuisb4def482010-10-15 13:48:342402 }
Bert Belder077f9d72012-02-15 22:34:182403#endif
Ben Noordhuis110a9cd2013-07-03 02:23:442404 info.GetReturnValue().Set(rc);
Ben Noordhuisb4def482010-10-15 13:48:342405}
2406
2407
Ben Noordhuis110a9cd2013-07-03 02:23:442408static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
Fedor Indutny75adde02014-02-21 13:02:422409 Environment* env = Environment::GetCurrent(info.GetIsolate());
2410 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182411#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:342412 int size = 0;
Fedor Indutny2bc30f22013-10-16 16:57:262413 while (environ[size])
2414 size++;
Ben Noordhuisb4def482010-10-15 13:48:342415
Fedor Indutnyce04c722014-03-13 16:38:142416 Local<Array> envarr = Array::New(env->isolate(), size);
Ben Noordhuisb4def482010-10-15 13:48:342417
2418 for (int i = 0; i < size; ++i) {
2419 const char* var = environ[i];
2420 const char* s = strchr(var, '=');
2421 const int length = s ? s - var : strlen(var);
Fedor Indutny75adde02014-02-21 13:02:422422 Local<String> name = String::NewFromUtf8(env->isolate(),
Ben Noordhuisf674b092013-08-07 19:50:412423 var,
2424 String::kNormalString,
2425 length);
Fedor Indutny75adde02014-02-21 13:02:422426 envarr->Set(i, name);
Ben Noordhuisb4def482010-10-15 13:48:342427 }
Bert Belder077f9d72012-02-15 22:34:182428#else // _WIN32
2429 WCHAR* environment = GetEnvironmentStringsW();
Fedor Indutny2bc30f22013-10-16 16:57:262430 if (environment == NULL)
2431 return; // This should not happen.
Fedor Indutnyce04c722014-03-13 16:38:142432 Local<Array> envarr = Array::New(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182433 WCHAR* p = environment;
2434 int i = 0;
2435 while (*p != NULL) {
2436 WCHAR *s;
2437 if (*p == L'=') {
2438 // If the key starts with '=' it is a hidden environment variable.
2439 p += wcslen(p) + 1;
2440 continue;
2441 } else {
2442 s = wcschr(p, L'=');
2443 }
2444 if (!s) {
2445 s = p + wcslen(p);
2446 }
Ben Noordhuisf674b092013-08-07 19:50:412447 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
Ben Noordhuis78f709d2013-08-09 15:43:102448 const size_t two_byte_buffer_len = s - p;
Fedor Indutny75adde02014-02-21 13:02:422449 Local<String> value = String::NewFromTwoByte(env->isolate(),
Ben Noordhuis78f709d2013-08-09 15:43:102450 two_byte_buffer,
2451 String::kNormalString,
2452 two_byte_buffer_len);
Fedor Indutny75adde02014-02-21 13:02:422453 envarr->Set(i++, value);
Bert Belder077f9d72012-02-15 22:34:182454 p = s + wcslen(s) + 1;
2455 }
2456 FreeEnvironmentStringsW(environment);
2457#endif
Ben Noordhuis110a9cd2013-07-03 02:23:442458
Fedor Indutny75adde02014-02-21 13:02:422459 info.GetReturnValue().Set(envarr);
Ben Noordhuisb4def482010-10-15 13:48:342460}
2461
2462
Fedor Indutny75adde02014-02-21 13:02:422463static Handle<Object> GetFeatures(Environment* env) {
Fedor Indutnyce04c722014-03-13 16:38:142464 EscapableHandleScope scope(env->isolate());
Ben Noordhuisaa0308d2011-07-23 21:16:482465
Fedor Indutnyce04c722014-03-13 16:38:142466 Local<Object> obj = Object::New(env->isolate());
Ryan Dahl52a40e02011-08-24 21:16:352467#if defined(DEBUG) && DEBUG
Fedor Indutny75adde02014-02-21 13:02:422468 Local<Value> debug = True(env->isolate());
Ryan Dahl52a40e02011-08-24 21:16:352469#else
Fedor Indutny75adde02014-02-21 13:02:422470 Local<Value> debug = False(env->isolate());
Fedor Indutny8e29ce92013-07-31 18:07:292471#endif // defined(DEBUG) && DEBUG
2472
Fedor Indutny75adde02014-02-21 13:02:422473 obj->Set(env->debug_string(), debug);
Ryan Dahl52a40e02011-08-24 21:16:352474
Fedor Indutny75adde02014-02-21 13:02:422475 obj->Set(env->uv_string(), True(env->isolate()));
Fedor Indutny8e29ce92013-07-31 18:07:292476 // TODO(bnoordhuis) ping libuv
Fedor Indutny75adde02014-02-21 13:02:422477 obj->Set(env->ipv6_lc_string(), True(env->isolate()));
Ben Noordhuisf674b092013-08-07 19:50:412478
Ben Noordhuis8d567f42013-08-27 14:14:452479#ifdef OPENSSL_NPN_NEGOTIATED
Fedor Indutny75adde02014-02-21 13:02:422480 Local<Boolean> tls_npn = True(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452481#else
Fedor Indutny75adde02014-02-21 13:02:422482 Local<Boolean> tls_npn = False(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452483#endif
Fedor Indutny75adde02014-02-21 13:02:422484 obj->Set(env->tls_npn_string(), tls_npn);
Ben Noordhuis8d567f42013-08-27 14:14:452485
2486#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
Fedor Indutny75adde02014-02-21 13:02:422487 Local<Boolean> tls_sni = True(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452488#else
Fedor Indutny75adde02014-02-21 13:02:422489 Local<Boolean> tls_sni = False(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452490#endif
Fedor Indutny75adde02014-02-21 13:02:422491 obj->Set(env->tls_sni_string(), tls_sni);
Ben Noordhuis8d567f42013-08-27 14:14:452492
Fedor Indutnyb3ef2892014-04-14 17:15:572493#if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2494 Local<Boolean> tls_ocsp = True(env->isolate());
2495#else
2496 Local<Boolean> tls_ocsp = False(env->isolate());
2497#endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2498 obj->Set(env->tls_ocsp_string(), tls_ocsp);
2499
Fedor Indutny75adde02014-02-21 13:02:422500 obj->Set(env->tls_string(),
Fedor Indutnyce04c722014-03-13 16:38:142501 Boolean::New(env->isolate(), get_builtin_module("crypto") != NULL));
Ben Noordhuisaa0308d2011-07-23 21:16:482502
Fedor Indutnyce04c722014-03-13 16:38:142503 return scope.Escape(obj);
Ben Noordhuisaa0308d2011-07-23 21:16:482504}
2505
2506
Ben Noordhuis110a9cd2013-07-03 02:23:442507static void DebugPortGetter(Local<String> property,
2508 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422509 Environment* env = Environment::GetCurrent(info.GetIsolate());
2510 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442511 info.GetReturnValue().Set(debug_port);
Fedor Indutny3f43b1c2012-02-12 15:53:432512}
2513
2514
2515static void DebugPortSetter(Local<String> property,
2516 Local<Value> value,
Ben Noordhuis110a9cd2013-07-03 02:23:442517 const PropertyCallbackInfo<void>& info) {
Fedor Indutny75adde02014-02-21 13:02:422518 Environment* env = Environment::GetCurrent(info.GetIsolate());
2519 HandleScope scope(env->isolate());
Rasmus Christian Pedersen734fb492014-09-18 12:10:532520 debug_port = value->Int32Value();
Fedor Indutny3f43b1c2012-02-12 15:53:432521}
2522
2523
Ben Noordhuis110a9cd2013-07-03 02:23:442524static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2525static void DebugPause(const FunctionCallbackInfo<Value>& args);
2526static void DebugEnd(const FunctionCallbackInfo<Value>& args);
Bert Belder829735e2011-11-04 15:23:022527
Shigeki Ohtsucd372512013-02-06 02:13:022528
Ben Noordhuis110a9cd2013-07-03 02:23:442529void NeedImmediateCallbackGetter(Local<String> property,
2530 const PropertyCallbackInfo<Value>& info) {
Ben Noordhuis09724b32013-11-11 21:02:032531 HandleScope handle_scope(info.GetIsolate());
Ben Noordhuis756b6222013-08-10 22:26:112532 Environment* env = Environment::GetCurrent(info.GetIsolate());
2533 const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2534 bool active = uv_is_active(
2535 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2536 info.GetReturnValue().Set(active);
Shigeki Ohtsucd372512013-02-06 02:13:022537}
2538
2539
Ben Noordhuis756b6222013-08-10 22:26:112540static void NeedImmediateCallbackSetter(
2541 Local<String> property,
2542 Local<Value> value,
2543 const PropertyCallbackInfo<void>& info) {
Ben Noordhuis756b6222013-08-10 22:26:112544 HandleScope handle_scope(info.GetIsolate());
Ben Noordhuis09724b32013-11-11 21:02:032545 Environment* env = Environment::GetCurrent(info.GetIsolate());
Shigeki Ohtsucd372512013-02-06 02:13:022546
Ben Noordhuis756b6222013-08-10 22:26:112547 uv_check_t* immediate_check_handle = env->immediate_check_handle();
2548 bool active = uv_is_active(
2549 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
Shigeki Ohtsucd372512013-02-06 02:13:022550
Ben Noordhuis756b6222013-08-10 22:26:112551 if (active == value->BooleanValue())
2552 return;
Shigeki Ohtsucd372512013-02-06 02:13:022553
Ben Noordhuis756b6222013-08-10 22:26:112554 uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
Shigeki Ohtsucd372512013-02-06 02:13:022555
Ben Noordhuis756b6222013-08-10 22:26:112556 if (active) {
2557 uv_check_stop(immediate_check_handle);
2558 uv_idle_stop(immediate_idle_handle);
Shigeki Ohtsucd372512013-02-06 02:13:022559 } else {
Ben Noordhuis756b6222013-08-10 22:26:112560 uv_check_start(immediate_check_handle, CheckImmediate);
2561 // Idle handle is needed only to stop the event loop from blocking in poll.
2562 uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
Shigeki Ohtsucd372512013-02-06 02:13:022563 }
2564}
2565
2566
Saúl Ibarra Corretgé42b93432014-03-12 23:08:292567void SetIdle(uv_prepare_t* handle) {
Ben Noordhuisf6496262013-10-03 09:03:462568 Environment* env = Environment::from_idle_prepare_handle(handle);
2569 env->isolate()->GetCpuProfiler()->SetIdle(true);
2570}
2571
2572
Saúl Ibarra Corretgé42b93432014-03-12 23:08:292573void ClearIdle(uv_check_t* handle) {
Ben Noordhuisf6496262013-10-03 09:03:462574 Environment* env = Environment::from_idle_check_handle(handle);
2575 env->isolate()->GetCpuProfiler()->SetIdle(false);
2576}
2577
2578
2579void StartProfilerIdleNotifier(Environment* env) {
2580 uv_prepare_start(env->idle_prepare_handle(), SetIdle);
2581 uv_check_start(env->idle_check_handle(), ClearIdle);
2582}
2583
2584
2585void StopProfilerIdleNotifier(Environment* env) {
2586 uv_prepare_stop(env->idle_prepare_handle());
2587 uv_check_stop(env->idle_check_handle());
2588}
2589
2590
2591void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis09724b32013-11-11 21:02:032592 HandleScope handle_scope(args.GetIsolate());
2593 Environment* env = Environment::GetCurrent(args.GetIsolate());
2594 StartProfilerIdleNotifier(env);
Ben Noordhuisf6496262013-10-03 09:03:462595}
2596
2597
2598void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis09724b32013-11-11 21:02:032599 HandleScope handle_scope(args.GetIsolate());
2600 Environment* env = Environment::GetCurrent(args.GetIsolate());
2601 StopProfilerIdleNotifier(env);
Ben Noordhuisf6496262013-10-03 09:03:462602}
2603
2604
Trevor Norrisc80f8fa2013-08-01 21:53:522605#define READONLY_PROPERTY(obj, str, var) \
2606 do { \
Fedor Indutny383b0c02014-10-08 10:34:512607 obj->ForceSet(OneByteString(env->isolate(), str), var, v8::ReadOnly); \
Trevor Norrisc80f8fa2013-08-01 21:53:522608 } while (0)
2609
2610
Ben Noordhuis756b6222013-08-10 22:26:112611void SetupProcessObject(Environment* env,
2612 int argc,
2613 const char* const* argv,
2614 int exec_argc,
2615 const char* const* exec_argv) {
Fedor Indutny75adde02014-02-21 13:02:422616 HandleScope scope(env->isolate());
Ryan Dahlcd1ec272011-01-02 09:44:422617
Ben Noordhuis756b6222013-08-10 22:26:112618 Local<Object> process = env->process_object();
Ben Noordhuis74a82152012-02-03 15:32:002619
Fedor Indutny75adde02014-02-21 13:02:422620 process->SetAccessor(env->title_string(),
Ryan Dahl5185c152010-06-18 07:26:492621 ProcessTitleGetter,
2622 ProcessTitleSetter);
2623
Ryan Dahlf4811832009-11-02 23:21:002624 // process.version
Ben Noordhuisf674b092013-08-07 19:50:412625 READONLY_PROPERTY(process,
2626 "version",
Fedor Indutny75adde02014-02-21 13:02:422627 FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
Ryan Dahl39b432e2010-08-17 18:24:102628
Ryan Dahlea9ee1f2011-07-28 02:30:322629 // process.moduleLoadList
Ben Noordhuis756b6222013-08-10 22:26:112630 READONLY_PROPERTY(process,
2631 "moduleLoadList",
2632 env->module_load_list_array());
Ryan Dahlea9ee1f2011-07-28 02:30:322633
Nathan Rajlich35043ad2012-03-13 23:04:172634 // process.versions
Fedor Indutnyce04c722014-03-13 16:38:142635 Local<Object> versions = Object::New(env->isolate());
Trevor Norrisc80f8fa2013-08-01 21:53:522636 READONLY_PROPERTY(process, "versions", versions);
Ben Noordhuisf674b092013-08-07 19:50:412637
2638 const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2639 "."
2640 NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR);
2641 READONLY_PROPERTY(versions,
2642 "http_parser",
Fedor Indutny75adde02014-02-21 13:02:422643 FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
Ben Noordhuisf674b092013-08-07 19:50:412644
Ryan Dahl39b432e2010-08-17 18:24:102645 // +1 to get rid of the leading 'v'
Ben Noordhuisf674b092013-08-07 19:50:412646 READONLY_PROPERTY(versions,
2647 "node",
Fedor Indutny75adde02014-02-21 13:02:422648 OneByteString(env->isolate(), NODE_VERSION + 1));
Ben Noordhuisf674b092013-08-07 19:50:412649 READONLY_PROPERTY(versions,
2650 "v8",
Fedor Indutny75adde02014-02-21 13:02:422651 OneByteString(env->isolate(), V8::GetVersion()));
Ben Noordhuisf674b092013-08-07 19:50:412652 READONLY_PROPERTY(versions,
2653 "uv",
Fedor Indutny75adde02014-02-21 13:02:422654 OneByteString(env->isolate(), uv_version_string()));
Ben Noordhuisf674b092013-08-07 19:50:412655 READONLY_PROPERTY(versions,
2656 "zlib",
Fedor Indutny75adde02014-02-21 13:02:422657 FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
Ben Noordhuisf674b092013-08-07 19:50:412658
2659 const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
Fedor Indutny75adde02014-02-21 13:02:422660 READONLY_PROPERTY(
2661 versions,
2662 "modules",
2663 FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
Ben Noordhuisf674b092013-08-07 19:50:412664
Peter Bright13d6a1f2011-08-06 04:23:252665#if HAVE_OPENSSL
Ryan Dahlcd1ec272011-01-02 09:44:422666 // Stupid code to slice out the version string.
Ben Noordhuis7acdabb2013-11-04 21:42:482667 { // NOLINT(whitespace/braces)
Ben Noordhuis962686b2013-11-03 20:00:372668 size_t i, j, k;
2669 int c;
2670 for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
2671 c = OPENSSL_VERSION_TEXT[i];
2672 if ('0' <= c && c <= '9') {
2673 for (j = i + 1; j < k; ++j) {
2674 c = OPENSSL_VERSION_TEXT[j];
2675 if (c == ' ')
2676 break;
2677 }
2678 break;
Ryan Dahlcd1ec272011-01-02 09:44:422679 }
Ryan Dahlcd1ec272011-01-02 09:44:422680 }
Ben Noordhuis962686b2013-11-03 20:00:372681 READONLY_PROPERTY(
2682 versions,
2683 "openssl",
Fedor Indutny75adde02014-02-21 13:02:422684 OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
Ryan Dahlcd1ec272011-01-02 09:44:422685 }
Ryan Dahlcd1ec272011-01-02 09:44:422686#endif
Ryan Dahl39b432e2010-08-17 18:24:102687
Nathan Rajlichb1be5402011-04-26 03:24:512688 // process.arch
Fedor Indutny75adde02014-02-21 13:02:422689 READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), ARCH));
Nathan Rajlichb1be5402011-04-26 03:24:512690
Ryan Dahlf4811832009-11-02 23:21:002691 // process.platform
Ben Noordhuisf674b092013-08-07 19:50:412692 READONLY_PROPERTY(process,
2693 "platform",
Fedor Indutny75adde02014-02-21 13:02:422694 OneByteString(env->isolate(), PLATFORM));
Ryan Dahlf4811832009-11-02 23:21:002695
Ryan Dahlf3ad6352010-02-03 20:19:082696 // process.argv
Fedor Indutnyce04c722014-03-13 16:38:142697 Local<Array> arguments = Array::New(env->isolate(), argc);
Ben Noordhuis185c5152013-09-02 14:42:012698 for (int i = 0; i < argc; ++i) {
Fedor Indutny75adde02014-02-21 13:02:422699 arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
Ryan27b268b2009-06-17 13:05:442700 }
Fedor Indutny75adde02014-02-21 13:02:422701 process->Set(env->argv_string(), arguments);
Ryan27b268b2009-06-17 13:05:442702
Micheil Smith19fd5302012-03-05 17:53:152703 // process.execArgv
Fedor Indutnyce04c722014-03-13 16:38:142704 Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
Ben Noordhuis185c5152013-09-02 14:42:012705 for (int i = 0; i < exec_argc; ++i) {
Fedor Indutny75adde02014-02-21 13:02:422706 exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
Micheil Smith19fd5302012-03-05 17:53:152707 }
Fedor Indutny75adde02014-02-21 13:02:422708 process->Set(env->exec_argv_string(), exec_arguments);
Micheil Smith19fd5302012-03-05 17:53:152709
Ryan Dahlf3ad6352010-02-03 20:19:082710 // create process.env
Fedor Indutnyce04c722014-03-13 16:38:142711 Local<ObjectTemplate> process_env_template =
2712 ObjectTemplate::New(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:112713 process_env_template->SetNamedPropertyHandler(EnvGetter,
2714 EnvSetter,
2715 EnvQuery,
2716 EnvDeleter,
2717 EnvEnumerator,
Fedor Indutnyce04c722014-03-13 16:38:142718 Object::New(env->isolate()));
Ben Noordhuis756b6222013-08-10 22:26:112719 Local<Object> process_env = process_env_template->NewInstance();
Fedor Indutny75adde02014-02-21 13:02:422720 process->Set(env->env_string(), process_env);
Ryan Dahlf3ad6352010-02-03 20:19:082721
Fedor Indutnyce04c722014-03-13 16:38:142722 READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
Fedor Indutny75adde02014-02-21 13:02:422723 READONLY_PROPERTY(process, "features", GetFeatures(env));
2724 process->SetAccessor(env->need_imm_cb_string(),
Ben Noordhuisf674b092013-08-07 19:50:412725 NeedImmediateCallbackGetter,
2726 NeedImmediateCallbackSetter);
Ryandc39e822009-09-10 12:07:352727
TJ Holowaychuk9481bc12010-10-07 02:05:012728 // -e, --eval
2729 if (eval_string) {
Ben Noordhuisf674b092013-08-07 19:50:412730 READONLY_PROPERTY(process,
2731 "_eval",
Fedor Indutny75adde02014-02-21 13:02:422732 String::NewFromUtf8(env->isolate(), eval_string));
Nathan Rajlichef3a8742012-04-24 08:24:132733 }
2734
2735 // -p, --print
2736 if (print_eval) {
Fedor Indutny75adde02014-02-21 13:02:422737 READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
TJ Holowaychuk9481bc12010-10-07 02:05:012738 }
2739
Nathan Rajlich6292df62012-04-24 08:32:332740 // -i, --interactive
Nathan Rajlichfeaa8a42012-03-21 07:05:252741 if (force_repl) {
Fedor Indutny75adde02014-02-21 13:02:422742 READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
Nathan Rajlichfeaa8a42012-03-21 07:05:252743 }
2744
isaacs5b399292012-06-21 18:42:332745 // --no-deprecation
2746 if (no_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422747 READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
isaacs5b399292012-06-21 18:42:332748 }
2749
isaacs5038f402013-03-06 01:46:372750 // --throw-deprecation
2751 if (throw_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422752 READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
isaacs5038f402013-03-06 01:46:372753 }
2754
isaacs5b399292012-06-21 18:42:332755 // --trace-deprecation
2756 if (trace_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422757 READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
isaacs5b399292012-06-21 18:42:332758 }
2759
Ben Noordhuisf674b092013-08-07 19:50:412760 size_t exec_path_len = 2 * PATH_MAX;
2761 char* exec_path = new char[exec_path_len];
2762 Local<String> exec_path_value;
2763 if (uv_exepath(exec_path, &exec_path_len) == 0) {
Fedor Indutny75adde02014-02-21 13:02:422764 exec_path_value = String::NewFromUtf8(env->isolate(),
Ben Noordhuisf674b092013-08-07 19:50:412765 exec_path,
2766 String::kNormalString,
2767 exec_path_len);
Marshall Culpepperca35ba62010-06-22 06:31:192768 } else {
Fedor Indutny75adde02014-02-21 13:02:422769 exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
Marshall Culpepperca35ba62010-06-22 06:31:192770 }
Fedor Indutny75adde02014-02-21 13:02:422771 process->Set(env->exec_path_string(), exec_path_value);
Ben Noordhuisf674b092013-08-07 19:50:412772 delete[] exec_path;
Marshall Culpepperca35ba62010-06-22 06:31:192773
Fedor Indutny75adde02014-02-21 13:02:422774 process->SetAccessor(env->debug_port_string(),
Fedor Indutny3f43b1c2012-02-12 15:53:432775 DebugPortGetter,
2776 DebugPortSetter);
2777
Ryan Dahl38814552009-10-09 15:15:472778 // define various internal methods
Ben Noordhuisf6496262013-10-03 09:03:462779 NODE_SET_METHOD(process,
2780 "_startProfilerIdleNotifier",
2781 StartProfilerIdleNotifier);
2782 NODE_SET_METHOD(process,
2783 "_stopProfilerIdleNotifier",
2784 StopProfilerIdleNotifier);
Ben Noordhuis5f040652012-04-28 16:45:102785 NODE_SET_METHOD(process, "_getActiveRequests", GetActiveRequests);
2786 NODE_SET_METHOD(process, "_getActiveHandles", GetActiveHandles);
Ryan Dahlad0a4ce2009-10-29 22:34:102787 NODE_SET_METHOD(process, "reallyExit", Exit);
Robert Mustacchi22404862011-12-15 01:02:152788 NODE_SET_METHOD(process, "abort", Abort);
Brandon Beacher47fcf782009-11-03 18:13:382789 NODE_SET_METHOD(process, "chdir", Chdir);
Ryan Dahlad0a4ce2009-10-29 22:34:102790 NODE_SET_METHOD(process, "cwd", Cwd);
Bert Belder30bab522010-11-25 00:09:062791
Ryan Dahlacc120a2011-08-09 20:53:562792 NODE_SET_METHOD(process, "umask", Umask);
2793
Linus Mårtensson5e4e8ec2013-05-08 12:10:072794#if defined(__POSIX__) && !defined(__ANDROID__)
Michael Cartera3860762010-02-08 06:13:102795 NODE_SET_METHOD(process, "getuid", GetUid);
2796 NODE_SET_METHOD(process, "setuid", SetUid);
James Duncandf1c1e52010-02-23 22:45:022797
2798 NODE_SET_METHOD(process, "setgid", SetGid);
2799 NODE_SET_METHOD(process, "getgid", GetGid);
Ben Noordhuis3ece1302012-12-04 05:36:232800
2801 NODE_SET_METHOD(process, "getgroups", GetGroups);
2802 NODE_SET_METHOD(process, "setgroups", SetGroups);
2803 NODE_SET_METHOD(process, "initgroups", InitGroups);
Fedor Indutny8e29ce92013-07-31 18:07:292804#endif // __POSIX__ && !defined(__ANDROID__)
James Duncandf1c1e52010-02-23 22:45:022805
Ryan Dahl6eca9482010-09-17 06:13:032806 NODE_SET_METHOD(process, "_kill", Kill);
Bert Belder30bab522010-11-25 00:09:062807
Bert Belder829735e2011-11-04 15:23:022808 NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
Fedor Indutnyb0388cc2011-12-10 16:52:072809 NODE_SET_METHOD(process, "_debugPause", DebugPause);
Fedor Indutny3f43b1c2012-02-12 15:53:432810 NODE_SET_METHOD(process, "_debugEnd", DebugEnd);
Bert Belder829735e2011-11-04 15:23:022811
Nathan Rajlich07c886f2012-03-05 16:51:582812 NODE_SET_METHOD(process, "hrtime", Hrtime);
2813
Bert Belderdd93c532011-10-28 10:05:092814 NODE_SET_METHOD(process, "dlopen", DLOpen);
2815
Tom Hughescf78ce52011-03-04 23:57:542816 NODE_SET_METHOD(process, "uptime", Uptime);
Ryan Dahlb3b3cfe2009-11-03 12:00:422817 NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
Ryan27b268b2009-06-17 13:05:442818
Ryan Dahl627fb5a2010-03-15 20:48:032819 NODE_SET_METHOD(process, "binding", Binding);
2820
Trevor Norrisefa62fd2013-09-24 21:12:112821 NODE_SET_METHOD(process, "_setupAsyncListener", SetupAsyncListener);
2822 NODE_SET_METHOD(process, "_setupNextTick", SetupNextTick);
Trevor Norris828f1452014-01-09 19:11:402823 NODE_SET_METHOD(process, "_setupDomainUse", SetupDomainUse);
Trevor Norrisf0b68892013-03-26 05:32:412824
Trevor Norris4f7f8bb2013-02-26 17:47:362825 // pre-set _events object for faster emit checks
Fedor Indutnyce04c722014-03-13 16:38:142826 process->Set(env->events_string(), Object::New(env->isolate()));
Dean McNameef67e8f22011-03-15 22:39:162827}
2828
2829
Trevor Norrisc80f8fa2013-08-01 21:53:522830#undef READONLY_PROPERTY
2831
2832
Dean McNameef67e8f22011-03-15 22:39:162833static void AtExit() {
Ryan Dahl4e43afd2011-09-30 20:11:472834 uv_tty_reset_mode();
Dean McNameef67e8f22011-03-15 22:39:162835}
2836
2837
Geir Haugec61b0e92014-03-31 07:52:032838static void SignalExit(int signo) {
Ryan Dahl4e43afd2011-09-30 20:11:472839 uv_tty_reset_mode();
Geir Haugec61b0e92014-03-31 07:52:032840 raise(signo);
Dean McNameef67e8f22011-03-15 22:39:162841}
2842
2843
isaacs906a1752013-08-21 22:36:502844// Most of the time, it's best to use `console.error` to write
2845// to the process.stderr stream. However, in some cases, such as
2846// when debugging the stream.Writable class or the process.nextTick
2847// function, it is useful to bypass JavaScript entirely.
2848static void RawDebug(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:422849 Environment* env = Environment::GetCurrent(args.GetIsolate());
2850 HandleScope scope(env->isolate());
isaacs906a1752013-08-21 22:36:502851
2852 assert(args.Length() == 1 && args[0]->IsString() &&
2853 "must be called with a single string");
2854
Timothy J Fontaine1a09da62014-06-10 23:36:042855 node::Utf8Value message(args[0]);
isaacs906a1752013-08-21 22:36:502856 fprintf(stderr, "%s\n", *message);
2857 fflush(stderr);
2858}
2859
2860
Fedor Indutny6a610a02014-10-04 14:44:392861void LoadEnvironment(Environment* env) {
Fedor Indutny75adde02014-02-21 13:02:422862 HandleScope handle_scope(env->isolate());
Ben Noordhuis34b0a362013-07-29 03:07:072863
Fedor Indutny6a610a02014-10-04 14:44:392864 V8::SetFatalErrorHandler(node::OnFatalError);
2865 V8::AddMessageListener(OnMessage);
2866
Ryan Dahl9f5643f2010-01-31 07:22:342867 // Compile, execute the src/node.js file. (Which was included as static C
2868 // string in node_natives.h. 'natve_node' is the string containing that
2869 // source code.)
Ryan Dahlb20c3432010-02-12 05:55:082870
Ryan Dahl9f5643f2010-01-31 07:22:342871 // The node.js file returns a function 'f'
Dean McNameef67e8f22011-03-15 22:39:162872 atexit(AtExit);
2873
Ryan Dahl9f5643f2010-01-31 07:22:342874 TryCatch try_catch;
Ryan Dahl9f5643f2010-01-31 07:22:342875
Miroslav Bajtosc16963b2013-06-17 19:19:592876 // Disable verbose mode to stop FatalException() handler from trying
2877 // to handle the exception. Errors this early in the start-up phase
2878 // are not safe to ignore.
2879 try_catch.SetVerbose(false);
2880
Fedor Indutnyf1de13b2014-02-05 16:38:332881 Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js");
Fedor Indutny75adde02014-02-21 13:02:422882 Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
Ryan Dahl9f5643f2010-01-31 07:22:342883 if (try_catch.HasCaught()) {
Fedor Indutnyf1de13b2014-02-05 16:38:332884 ReportException(env, try_catch);
Ryan Dahl9f5643f2010-01-31 07:22:342885 exit(10);
2886 }
Ryan Dahl9f5643f2010-01-31 07:22:342887 assert(f_value->IsFunction());
2888 Local<Function> f = Local<Function>::Cast(f_value);
2889
2890 // Now we call 'f' with the 'process' variable that we've built up with
2891 // all our bindings. Inside node.js we'll take care of assigning things to
2892 // their places.
Ryan Dahlb20c3432010-02-12 05:55:082893
Ryan Dahl9f5643f2010-01-31 07:22:342894 // We start the process this way in order to be more modular. Developers
2895 // who do not like how 'src/node.js' setups the module system but do like
2896 // Node's I/O bindings may want to replace 'f' with their own function.
2897
Ryan Dahlf8ce8482010-09-17 07:01:072898 // Add a reference to the global object
Ben Noordhuis756b6222013-08-10 22:26:112899 Local<Object> global = env->context()->Global();
Zoran Tomicicd98ea702010-02-22 05:15:442900
Ben Noordhuisc4def502013-10-28 19:18:592901#if defined HAVE_DTRACE || defined HAVE_ETW
Fedor Indutny75adde02014-02-21 13:02:422902 InitDTrace(env, global);
Ryan Dahle9257b82011-02-10 02:50:262903#endif
Ryan Dahl068b7332011-01-25 01:50:102904
Scott Blomquistf657ce62012-11-20 23:27:222905#if defined HAVE_PERFCTR
Fedor Indutny75adde02014-02-21 13:02:422906 InitPerfCounters(env, global);
Scott Blomquistf657ce62012-11-20 23:27:222907#endif
2908
Miroslav Bajtosc16963b2013-06-17 19:19:592909 // Enable handling of uncaught exceptions
2910 // (FatalException(), break on uncaught exception in debugger)
2911 //
2912 // This is not strictly necessary since it's almost impossible
2913 // to attach the debugger fast enought to break on exception
2914 // thrown during process startup.
2915 try_catch.SetVerbose(true);
Ryan Dahl9f5643f2010-01-31 07:22:342916
Ben Noordhuis756b6222013-08-10 22:26:112917 NODE_SET_METHOD(env->process_object(), "_rawDebug", RawDebug);
isaacs906a1752013-08-21 22:36:502918
Ben Noordhuis756b6222013-08-10 22:26:112919 Local<Value> arg = env->process_object();
Ben Noordhuis110a9cd2013-07-03 02:23:442920 f->Call(global, 1, &arg);
Ryan27b268b2009-06-17 13:05:442921}
2922
Zoran Tomicicd98ea702010-02-22 05:15:442923static void PrintHelp();
2924
Ben Noordhuisbd9c6662013-11-16 13:39:412925static bool ParseDebugOpt(const char* arg) {
2926 const char* port = NULL;
Zoran Tomicicd98ea702010-02-22 05:15:442927
Ben Noordhuisbd9c6662013-11-16 13:39:412928 if (!strcmp(arg, "--debug")) {
Miroslav Bajtoš43ec1b12013-05-02 06:34:222929 use_debug_agent = true;
Ben Noordhuisbd9c6662013-11-16 13:39:412930 } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
2931 use_debug_agent = true;
2932 port = arg + sizeof("--debug=") - 1;
2933 } else if (!strcmp(arg, "--debug-brk")) {
2934 use_debug_agent = true;
2935 debug_wait_connect = true;
2936 } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
2937 use_debug_agent = true;
2938 debug_wait_connect = true;
2939 port = arg + sizeof("--debug-brk=") - 1;
2940 } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
2941 port = arg + sizeof("--debug-port=") - 1;
2942 } else {
2943 return false;
2944 }
2945
2946 if (port != NULL) {
2947 debug_port = atoi(port);
2948 if (debug_port < 1024 || debug_port > 65535) {
2949 fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
2950 PrintHelp();
2951 exit(12);
Miroslav Bajtoš43ec1b12013-05-02 06:34:222952 }
Zoran Tomicicd98ea702010-02-22 05:15:442953 }
Zoran Tomicicd98ea702010-02-22 05:15:442954
Ben Noordhuisbd9c6662013-11-16 13:39:412955 return true;
Zoran Tomicicd98ea702010-02-22 05:15:442956}
2957
Ryand6c9d312009-09-11 14:02:292958static void PrintHelp() {
Steve Engledow292345f2011-07-05 11:07:082959 printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
Ryan Dahl87339a22011-10-12 09:56:292960 " node debug script.js [arguments] \n"
Ryan Dahl4fa712c2011-01-13 23:28:162961 "\n"
Ryan Dahl209b2192010-03-08 16:33:102962 "Options:\n"
Tom Hughes78da9cb2010-10-18 22:50:562963 " -v, --version print node's version\n"
Steve Engledow292345f2011-07-05 11:07:082964 " -e, --eval script evaluate script\n"
Ben Noordhuiscb6d0842012-10-20 13:03:482965 " -p, --print evaluate script and print result\n"
Nathan Rajlichfeaa8a42012-03-21 07:05:252966 " -i, --interactive always enter the REPL even if stdin\n"
2967 " does not appear to be a terminal\n"
isaacs5b399292012-06-21 18:42:332968 " --no-deprecation silence deprecation warnings\n"
Trevor Norrisf10fd1d2014-05-07 21:47:572969 " --throw-deprecation throw an exception anytime a deprecated "
2970 "function is used\n"
isaacs5b399292012-06-21 18:42:332971 " --trace-deprecation show stack traces on deprecations\n"
Tom Hughes78da9cb2010-10-18 22:50:562972 " --v8-options print v8 command line options\n"
Tom Hughes78da9cb2010-10-18 22:50:562973 " --max-stack-size=val set max v8 stack size (bytes)\n"
Steven R. Loomisac2857b2014-09-05 05:03:242974#if defined(NODE_HAVE_I18N_SUPPORT)
2975 " --icu-data-dir=dir set ICU data load path to dir\n"
2976 " (overrides NODE_ICU_DATA)\n"
2977#if !defined(NODE_HAVE_SMALL_ICU)
2978 " Note: linked-in ICU data is\n"
2979 " present.\n"
2980#endif
2981#endif
Ryan Dahl209b2192010-03-08 16:33:102982 "\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112983 "Environment variables:\n"
2984#ifdef _WIN32
2985 "NODE_PATH ';'-separated list of directories\n"
2986#else
Tom Hughes78da9cb2010-10-18 22:50:562987 "NODE_PATH ':'-separated list of directories\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112988#endif
isaacsc050d0f2011-07-25 01:04:452989 " prefixed to the module search path.\n"
Tom Hughes78da9cb2010-10-18 22:50:562990 "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
2991 " global contexts.\n"
Ryan Dahl4fa712c2011-01-13 23:28:162992 "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
Steven R. Loomisac2857b2014-09-05 05:03:242993#if defined(NODE_HAVE_I18N_SUPPORT)
2994 "NODE_ICU_DATA Data path for ICU (Intl object) data\n"
2995#if !defined(NODE_HAVE_SMALL_ICU)
2996 " (will extend linked-in data)\n"
2997#endif
2998#endif
Ryan Dahl209b2192010-03-08 16:33:102999 "\n"
Ryan Dahl4fa712c2011-01-13 23:28:163000 "Documentation can be found at http://nodejs.org/\n");
Ryan11df2522009-08-03 16:19:403001}
3002
Miroslav Bajtoš43ec1b12013-05-02 06:34:223003
Ben Noordhuis185c5152013-09-02 14:42:013004// Parse command line arguments.
3005//
3006// argv is modified in place. exec_argv and v8_argv are out arguments that
3007// ParseArgs() allocates memory for and stores a pointer to the output
3008// vector in. The caller should free them with delete[].
3009//
3010// On exit:
3011//
3012// * argv contains the arguments with node and V8 options filtered out.
3013// * exec_argv contains both node and V8 options and nothing else.
3014// * v8_argv contains argv[0] plus any V8 options
3015static void ParseArgs(int* argc,
3016 const char** argv,
3017 int* exec_argc,
3018 const char*** exec_argv,
3019 int* v8_argc,
3020 const char*** v8_argv) {
3021 const unsigned int nargs = static_cast<unsigned int>(*argc);
3022 const char** new_exec_argv = new const char*[nargs];
3023 const char** new_v8_argv = new const char*[nargs];
3024 const char** new_argv = new const char*[nargs];
Peter Griess78d33f42010-06-04 15:29:103025
Ben Noordhuis185c5152013-09-02 14:42:013026 for (unsigned int i = 0; i < nargs; ++i) {
3027 new_exec_argv[i] = NULL;
3028 new_v8_argv[i] = NULL;
3029 new_argv[i] = NULL;
3030 }
3031
3032 // exec_argv starts with the first option, the other two start with argv[0].
3033 unsigned int new_exec_argc = 0;
3034 unsigned int new_v8_argc = 1;
3035 unsigned int new_argc = 1;
3036 new_v8_argv[0] = argv[0];
3037 new_argv[0] = argv[0];
3038
3039 unsigned int index = 1;
3040 while (index < nargs && argv[index][0] == '-') {
3041 const char* const arg = argv[index];
3042 unsigned int args_consumed = 1;
3043
Ben Noordhuisbd9c6662013-11-16 13:39:413044 if (ParseDebugOpt(arg)) {
3045 // Done, consumed by ParseDebugOpt().
Ryan1910c112009-09-11 18:05:223046 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
Ryan11df2522009-08-03 16:19:403047 printf("%s\n", NODE_VERSION);
3048 exit(0);
3049 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
3050 PrintHelp();
3051 exit(0);
Ben Noordhuis185c5152013-09-02 14:42:013052 } else if (strcmp(arg, "--eval") == 0 ||
3053 strcmp(arg, "-e") == 0 ||
3054 strcmp(arg, "--print") == 0 ||
3055 strcmp(arg, "-pe") == 0 ||
Ben Noordhuisf03c3202012-09-03 14:42:183056 strcmp(arg, "-p") == 0) {
Ben Noordhuis83b1dda2012-09-04 12:19:593057 bool is_eval = strchr(arg, 'e') != NULL;
3058 bool is_print = strchr(arg, 'p') != NULL;
Ben Noordhuis83b1dda2012-09-04 12:19:593059 print_eval = print_eval || is_print;
Ben Noordhuis185c5152013-09-02 14:42:013060 // --eval, -e and -pe always require an argument.
Ben Noordhuis83b1dda2012-09-04 12:19:593061 if (is_eval == true) {
Ben Noordhuis185c5152013-09-02 14:42:013062 args_consumed += 1;
3063 eval_string = argv[index + 1];
3064 if (eval_string == NULL) {
3065 fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
isaacsb30a03e2013-09-07 00:47:563066 exit(9);
Ben Noordhuis185c5152013-09-02 14:42:013067 }
Alexis Campailla14d6df82013-12-28 08:12:403068 } else if ((index + 1 < nargs) &&
3069 argv[index + 1] != NULL &&
3070 argv[index + 1][0] != '-') {
Ben Noordhuis185c5152013-09-02 14:42:013071 args_consumed += 1;
3072 eval_string = argv[index + 1];
3073 if (strncmp(eval_string, "\\-", 2) == 0) {
3074 // Starts with "\\-": escaped expression, drop the backslash.
3075 eval_string += 1;
3076 }
Ben Noordhuis83b1dda2012-09-04 12:19:593077 }
Nathan Rajlichfeaa8a42012-03-21 07:05:253078 } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
3079 force_repl = true;
isaacs5b399292012-06-21 18:42:333080 } else if (strcmp(arg, "--no-deprecation") == 0) {
isaacs5b399292012-06-21 18:42:333081 no_deprecation = true;
3082 } else if (strcmp(arg, "--trace-deprecation") == 0) {
isaacs5b399292012-06-21 18:42:333083 trace_deprecation = true;
isaacs5038f402013-03-06 01:46:373084 } else if (strcmp(arg, "--throw-deprecation") == 0) {
isaacs5038f402013-03-06 01:46:373085 throw_deprecation = true;
Ben Noordhuis185c5152013-09-02 14:42:013086 } else if (strcmp(arg, "--v8-options") == 0) {
3087 new_v8_argv[new_v8_argc] = "--help";
3088 new_v8_argc += 1;
Steven R. Loomisac2857b2014-09-05 05:03:243089#if defined(NODE_HAVE_I18N_SUPPORT)
3090 } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3091 icu_data_dir = arg + 15;
3092#endif
Ben Noordhuis185c5152013-09-02 14:42:013093 } else {
3094 // V8 option. Pass through as-is.
3095 new_v8_argv[new_v8_argc] = arg;
3096 new_v8_argc += 1;
Ryan11df2522009-08-03 16:19:403097 }
Ben Noordhuis185c5152013-09-02 14:42:013098
3099 memcpy(new_exec_argv + new_exec_argc,
3100 argv + index,
3101 args_consumed * sizeof(*argv));
3102
3103 new_exec_argc += args_consumed;
3104 index += args_consumed;
Ryan11df2522009-08-03 16:19:403105 }
Peter Griess78d33f42010-06-04 15:29:103106
Ben Noordhuis185c5152013-09-02 14:42:013107 // Copy remaining arguments.
3108 const unsigned int args_left = nargs - index;
3109 memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
3110 new_argc += args_left;
3111
3112 *exec_argc = new_exec_argc;
3113 *exec_argv = new_exec_argv;
3114 *v8_argc = new_v8_argc;
3115 *v8_argv = new_v8_argv;
3116
3117 // Copy new_argv over argv and update argc.
3118 memcpy(argv, new_argv, new_argc * sizeof(*argv));
3119 delete[] new_argv;
3120 *argc = static_cast<int>(new_argc);
Ryan11df2522009-08-03 16:19:403121}
3122
Bert Belder829735e2011-11-04 15:23:023123
Peter Rybin688859a2012-07-03 19:21:373124// Called from V8 Debug Agent TCP thread.
Fedor Indutny6a610a02014-10-04 14:44:393125static void DispatchMessagesDebugAgentCallback(Environment* env) {
3126 // TODO(indutny): move async handle to environment
Peter Rybin688859a2012-07-03 19:21:373127 uv_async_send(&dispatch_debug_messages_async);
3128}
3129
3130
Fedor Indutny6a610a02014-10-04 14:44:393131static void StartDebug(Environment* env, bool wait) {
3132 CHECK(!debugger_running);
3133
3134 env->debugger_agent()->set_dispatch_handler(
3135 DispatchMessagesDebugAgentCallback);
3136 debugger_running = env->debugger_agent()->Start(debug_port, wait);
Ben Noordhuisca363cf2013-10-15 21:32:183137 if (debugger_running == false) {
3138 fprintf(stderr, "Starting debugger on port %d failed\n", debug_port);
3139 fflush(stderr);
3140 return;
3141 }
Fedor Indutny6a610a02014-10-04 14:44:393142}
Ben Noordhuisca363cf2013-10-15 21:32:183143
Ben Noordhuisca363cf2013-10-15 21:32:183144
Fedor Indutny6a610a02014-10-04 14:44:393145// Called from the main thread.
3146static void EnableDebug(Environment* env) {
3147 CHECK(debugger_running);
Fedor Indutny8398bf92014-04-27 08:42:433148
Fedor Indutny6a610a02014-10-04 14:44:393149 // Send message to enable debug in workers
3150 HandleScope handle_scope(env->isolate());
3151
Fedor Indutnyce04c722014-03-13 16:38:143152 Local<Object> message = Object::New(env->isolate());
Ben Noordhuisca363cf2013-10-15 21:32:183153 message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
3154 FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
3155 Local<Value> argv[] = {
3156 FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
Ben Noordhuis756b6222013-08-10 22:26:113157 message
Ben Noordhuisf674b092013-08-07 19:50:413158 };
Ben Noordhuisca363cf2013-10-15 21:32:183159 MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv);
Fedor Indutny6a610a02014-10-04 14:44:393160
3161 // Enabled debugger, possibly making it wait on a semaphore
3162 env->debugger_agent()->Enable();
Miroslav Bajtoš43ec1b12013-05-02 06:34:223163}
3164
3165
Ben Noordhuisca363cf2013-10-15 21:32:183166// Called from the main thread.
Saúl Ibarra Corretgé42b93432014-03-12 23:08:293167static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {
Ben Noordhuisca363cf2013-10-15 21:32:183168 if (debugger_running == false) {
3169 fprintf(stderr, "Starting debugger agent.\n");
Fedor Indutny6a610a02014-10-04 14:44:393170
3171 Environment* env = Environment::GetCurrent(node_isolate);
3172 Context::Scope context_scope(env->context());
3173
3174 StartDebug(env, false);
3175 EnableDebug(env);
Ben Noordhuis756b6222013-08-10 22:26:113176 }
Ben Noordhuisca363cf2013-10-15 21:32:183177 Isolate::Scope isolate_scope(node_isolate);
3178 v8::Debug::ProcessDebugMessages();
Ryan Dahl2a7e7b12010-12-18 19:17:293179}
3180
3181
Fedor Indutny82d0ac72011-09-24 13:51:593182#ifdef __POSIX__
Ben Noordhuis4234bcc2013-10-16 00:54:243183static volatile sig_atomic_t caught_early_debug_signal;
3184
3185
3186static void EarlyDebugSignalHandler(int signo) {
3187 caught_early_debug_signal = 1;
3188}
3189
3190
3191static void InstallEarlyDebugSignalHandler() {
3192 struct sigaction sa;
3193 memset(&sa, 0, sizeof(sa));
3194 sa.sa_handler = EarlyDebugSignalHandler;
3195 sigaction(SIGUSR1, &sa, NULL);
3196}
3197
3198
Ben Noordhuisca363cf2013-10-15 21:32:183199static void EnableDebugSignalHandler(int signo) {
3200 // Call only async signal-safe functions here!
3201 v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3202 uv_async_send(&dispatch_debug_messages_async);
Ryan Dahl2a7e7b12010-12-18 19:17:293203}
3204
3205
Geir Haugec61b0e92014-03-31 07:52:033206static void RegisterSignalHandler(int signal,
3207 void (*handler)(int signal),
3208 bool reset_handler = false) {
Tom Hughesf61b1102010-10-12 21:01:583209 struct sigaction sa;
Tom Hughesf61b1102010-10-12 21:01:583210 memset(&sa, 0, sizeof(sa));
3211 sa.sa_handler = handler;
Geir Haugec61b0e92014-03-31 07:52:033212 sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
Tom Hughesf61b1102010-10-12 21:01:583213 sigfillset(&sa.sa_mask);
Geir Haugec61b0e92014-03-31 07:52:033214 CHECK_EQ(sigaction(signal, &sa, NULL), 0);
Bert Belder829735e2011-11-04 15:23:023215}
3216
3217
Ben Noordhuis110a9cd2013-07-03 02:23:443218void DebugProcess(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:423219 Environment* env = Environment::GetCurrent(args.GetIsolate());
3220 HandleScope scope(env->isolate());
Bert Belder829735e2011-11-04 15:23:023221
3222 if (args.Length() != 1) {
Fedor Indutny75adde02014-02-21 13:02:423223 return env->ThrowError("Invalid number of arguments.");
Bert Belder829735e2011-11-04 15:23:023224 }
3225
3226 pid_t pid;
3227 int r;
3228
3229 pid = args[0]->IntegerValue();
3230 r = kill(pid, SIGUSR1);
3231 if (r != 0) {
Fedor Indutny75adde02014-02-21 13:02:423232 return env->ThrowErrnoException(errno, "kill");
Bert Belder829735e2011-11-04 15:23:023233 }
Tom Hughesf61b1102010-10-12 21:01:583234}
Ben Noordhuisca363cf2013-10-15 21:32:183235
3236
3237static int RegisterDebugSignalHandler() {
3238 // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3239 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
Ben Noordhuis4234bcc2013-10-16 00:54:243240 // If we caught a SIGUSR1 during the bootstrap process, re-raise it
3241 // now that the debugger infrastructure is in place.
Fedor Indutny2bc30f22013-10-16 16:57:263242 if (caught_early_debug_signal)
3243 raise(SIGUSR1);
Ben Noordhuisca363cf2013-10-15 21:32:183244 return 0;
3245}
Fedor Indutny8e29ce92013-07-31 18:07:293246#endif // __POSIX__
Tom Hughesf61b1102010-10-12 21:01:583247
3248
Bert Belder829735e2011-11-04 15:23:023249#ifdef _WIN32
3250DWORD WINAPI EnableDebugThreadProc(void* arg) {
Ben Noordhuisca363cf2013-10-15 21:32:183251 v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3252 uv_async_send(&dispatch_debug_messages_async);
Bert Belder829735e2011-11-04 15:23:023253 return 0;
3254}
3255
3256
Bert Belder8f2694b2012-02-16 21:19:483257static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
3258 size_t buf_len) {
3259 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
Bert Belder829735e2011-11-04 15:23:023260}
3261
3262
3263static int RegisterDebugSignalHandler() {
Bert Belder8f2694b2012-02-16 21:19:483264 wchar_t mapping_name[32];
Bert Belder829735e2011-11-04 15:23:023265 HANDLE mapping_handle;
3266 DWORD pid;
3267 LPTHREAD_START_ROUTINE* handler;
3268
3269 pid = GetCurrentProcessId();
3270
3271 if (GetDebugSignalHandlerMappingName(pid,
3272 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:483273 ARRAY_SIZE(mapping_name)) < 0) {
Bert Belder829735e2011-11-04 15:23:023274 return -1;
3275 }
3276
Bert Belder8f2694b2012-02-16 21:19:483277 mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
Bert Belder829735e2011-11-04 15:23:023278 NULL,
3279 PAGE_READWRITE,
3280 0,
3281 sizeof *handler,
3282 mapping_name);
3283 if (mapping_handle == NULL) {
3284 return -1;
3285 }
3286
Bert Belder8f2694b2012-02-16 21:19:483287 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3288 MapViewOfFile(mapping_handle,
3289 FILE_MAP_ALL_ACCESS,
3290 0,
3291 0,
3292 sizeof *handler));
Bert Belder829735e2011-11-04 15:23:023293 if (handler == NULL) {
3294 CloseHandle(mapping_handle);
3295 return -1;
3296 }
3297
3298 *handler = EnableDebugThreadProc;
3299
Fedor Indutny8e29ce92013-07-31 18:07:293300 UnmapViewOfFile(static_cast<void*>(handler));
Bert Belder829735e2011-11-04 15:23:023301
3302 return 0;
3303}
3304
3305
Ben Noordhuis110a9cd2013-07-03 02:23:443306static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
Alexis Campailla440b9e22014-02-24 18:55:273307 Isolate* isolate = args.GetIsolate();
3308 Environment* env = Environment::GetCurrent(isolate);
3309 HandleScope scope(isolate);
Bert Belder829735e2011-11-04 15:23:023310 DWORD pid;
Bert Belder68db2062012-02-03 14:37:463311 HANDLE process = NULL;
Bert Belder829735e2011-11-04 15:23:023312 HANDLE thread = NULL;
3313 HANDLE mapping = NULL;
Bert Belder8f2694b2012-02-16 21:19:483314 wchar_t mapping_name[32];
Bert Belder829735e2011-11-04 15:23:023315 LPTHREAD_START_ROUTINE* handler = NULL;
3316
3317 if (args.Length() != 1) {
Fedor Indutny75adde02014-02-21 13:02:423318 env->ThrowError("Invalid number of arguments.");
Bert Belder829735e2011-11-04 15:23:023319 goto out;
3320 }
3321
3322 pid = (DWORD) args[0]->IntegerValue();
3323
Bert Belder68db2062012-02-03 14:37:463324 process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
Bert Belder829735e2011-11-04 15:23:023325 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
3326 PROCESS_VM_READ,
3327 FALSE,
3328 pid);
Bert Belder68db2062012-02-03 14:37:463329 if (process == NULL) {
Alexis Campailla440b9e22014-02-24 18:55:273330 isolate->ThrowException(
3331 WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
Bert Belder829735e2011-11-04 15:23:023332 goto out;
3333 }
3334
3335 if (GetDebugSignalHandlerMappingName(pid,
3336 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:483337 ARRAY_SIZE(mapping_name)) < 0) {
Fedor Indutny75adde02014-02-21 13:02:423338 env->ThrowErrnoException(errno, "sprintf");
Bert Belder829735e2011-11-04 15:23:023339 goto out;
3340 }
3341
Bert Belder8f2694b2012-02-16 21:19:483342 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
Bert Belder829735e2011-11-04 15:23:023343 if (mapping == NULL) {
Alexis Campailla440b9e22014-02-24 18:55:273344 isolate->ThrowException(WinapiErrnoException(isolate,
Fedor Indutny75adde02014-02-21 13:02:423345 GetLastError(),
3346 "OpenFileMappingW"));
Bert Belder829735e2011-11-04 15:23:023347 goto out;
3348 }
3349
Bert Belder8f2694b2012-02-16 21:19:483350 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3351 MapViewOfFile(mapping,
3352 FILE_MAP_READ,
3353 0,
3354 0,
3355 sizeof *handler));
Bert Belder829735e2011-11-04 15:23:023356 if (handler == NULL || *handler == NULL) {
Alexis Campailla440b9e22014-02-24 18:55:273357 isolate->ThrowException(
3358 WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
Bert Belder829735e2011-11-04 15:23:023359 goto out;
3360 }
3361
Bert Belder68db2062012-02-03 14:37:463362 thread = CreateRemoteThread(process,
Bert Belder829735e2011-11-04 15:23:023363 NULL,
3364 0,
3365 *handler,
3366 NULL,
3367 0,
3368 NULL);
3369 if (thread == NULL) {
Alexis Campailla440b9e22014-02-24 18:55:273370 isolate->ThrowException(WinapiErrnoException(isolate,
3371 GetLastError(),
3372 "CreateRemoteThread"));
Bert Belder829735e2011-11-04 15:23:023373 goto out;
3374 }
3375
3376 // Wait for the thread to terminate
3377 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
Alexis Campailla440b9e22014-02-24 18:55:273378 isolate->ThrowException(WinapiErrnoException(isolate,
3379 GetLastError(),
3380 "WaitForSingleObject"));
Bert Belder829735e2011-11-04 15:23:023381 goto out;
3382 }
3383
3384 out:
Fedor Indutny8e29ce92013-07-31 18:07:293385 if (process != NULL)
3386 CloseHandle(process);
3387 if (thread != NULL)
Bert Belder829735e2011-11-04 15:23:023388 CloseHandle(thread);
Fedor Indutny8e29ce92013-07-31 18:07:293389 if (handler != NULL)
Bert Belder829735e2011-11-04 15:23:023390 UnmapViewOfFile(handler);
Fedor Indutny8e29ce92013-07-31 18:07:293391 if (mapping != NULL)
Bert Belder829735e2011-11-04 15:23:023392 CloseHandle(mapping);
Bert Belder829735e2011-11-04 15:23:023393}
Fedor Indutny8e29ce92013-07-31 18:07:293394#endif // _WIN32
Bert Belder829735e2011-11-04 15:23:023395
3396
Ben Noordhuis110a9cd2013-07-03 02:23:443397static void DebugPause(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:423398 v8::Debug::DebugBreak(args.GetIsolate());
Fedor Indutnyb0388cc2011-12-10 16:52:073399}
3400
3401
Ben Noordhuis110a9cd2013-07-03 02:23:443402static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny3f43b1c2012-02-12 15:53:433403 if (debugger_running) {
Fedor Indutny6a610a02014-10-04 14:44:393404 Environment* env = Environment::GetCurrent(args.GetIsolate());
3405 env->debugger_agent()->Stop();
Fedor Indutny3f43b1c2012-02-12 15:53:433406 debugger_running = false;
3407 }
Fedor Indutny3f43b1c2012-02-12 15:53:433408}
3409
3410
Ben Noordhuis185c5152013-09-02 14:42:013411void Init(int* argc,
3412 const char** argv,
3413 int* exec_argc,
3414 const char*** exec_argv) {
Ben Noordhuis74a82152012-02-03 15:32:003415 // Initialize prog_start_time to get relative uptime.
Rasmus Christian Pedersen734fb492014-09-18 12:10:533416 prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
Ben Noordhuis74a82152012-02-03 15:32:003417
Bert Belder09be3602012-06-13 23:28:513418 // Make inherited handles noninheritable.
3419 uv_disable_stdio_inheritance();
3420
Miroslav Bajtošfbf46412013-05-02 14:42:493421 // init async debug messages dispatching
Ben Noordhuis756b6222013-08-10 22:26:113422 // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
Miroslav Bajtošfbf46412013-05-02 14:42:493423 uv_async_init(uv_default_loop(),
3424 &dispatch_debug_messages_async,
3425 DispatchDebugMessagesAsyncCallback);
3426 uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
3427
Ben Noordhuis490d5ab2014-03-31 12:22:493428#if defined(NODE_V8_OPTIONS)
3429 // Should come before the call to V8::SetFlagsFromCommandLine()
3430 // so the user can disable a flag --foo at run-time by passing
3431 // --no_foo from the command line.
3432 V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
3433#endif
Fedor Indutnyb55c9d62014-03-26 20:30:493434
Ryan Dahl38814552009-10-09 15:15:473435 // Parse a few arguments which are specific to Node.
Ben Noordhuis185c5152013-09-02 14:42:013436 int v8_argc;
3437 const char** v8_argv;
3438 ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
Danny Coatesdc8c0792010-08-01 22:46:483439
Ben Noordhuis9566fe82013-10-03 08:45:323440 // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
3441 // manually? That would give us a little more control over its runtime
3442 // behavior but it could also interfere with the user's intentions in ways
3443 // we fail to anticipate. Dillema.
3444 for (int i = 1; i < v8_argc; ++i) {
3445 if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
3446 v8_is_profiling = true;
3447 break;
3448 }
3449 }
3450
Steven R. Loomisac2857b2014-09-05 05:03:243451#if defined(NODE_HAVE_I18N_SUPPORT)
3452 if (icu_data_dir == NULL) {
3453 // if the parameter isn't given, use the env variable.
3454 icu_data_dir = getenv("NODE_ICU_DATA");
3455 }
3456 // Initialize ICU.
3457 // If icu_data_dir is NULL here, it will load the 'minimal' data.
3458 if (!i18n::InitializeICUDirectory(icu_data_dir)) {
3459 FatalError(NULL, "Could not initialize ICU "
3460 "(check NODE_ICU_DATA or --icu-data-dir parameters)");
3461 }
3462#endif
Ben Noordhuis185c5152013-09-02 14:42:013463 // The const_cast doesn't violate conceptual const-ness. V8 doesn't modify
3464 // the argv array or the elements it points to.
3465 V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
3466
3467 // Anything that's still in v8_argv is not a V8 or a node option.
3468 for (int i = 1; i < v8_argc; i++) {
3469 fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
3470 }
3471 delete[] v8_argv;
3472 v8_argv = NULL;
3473
3474 if (v8_argc > 1) {
isaacsb30a03e2013-09-07 00:47:563475 exit(9);
Ryan Dahladec5442010-08-04 17:38:193476 }
Tom Hughes78da9cb2010-10-18 22:50:563477
Ben Noordhuis185c5152013-09-02 14:42:013478 if (debug_wait_connect) {
3479 const char expose_debug_as[] = "--expose_debug_as=v8debug";
3480 V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
3481 }
Ryan23376302009-09-10 10:34:293482
Ben Noordhuis0693d222013-06-29 06:16:253483 V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton);
3484
Bert Belder30bab522010-11-25 00:09:063485#ifdef __POSIX__
Ben Noordhuis68200542013-10-02 10:17:573486 // Raise the open file descriptor limit.
Trevor Norris7503e4c2013-10-04 03:43:353487 { // NOLINT (whitespace/braces)
Ben Noordhuis68200542013-10-02 10:17:573488 struct rlimit lim;
3489 if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
3490 // Do a binary search for the limit.
3491 rlim_t min = lim.rlim_cur;
3492 rlim_t max = 1 << 20;
3493 // But if there's a defined upper bound, don't search, just set it.
3494 if (lim.rlim_max != RLIM_INFINITY) {
3495 min = lim.rlim_max;
3496 max = lim.rlim_max;
3497 }
3498 do {
3499 lim.rlim_cur = min + (max - min) / 2;
3500 if (setrlimit(RLIMIT_NOFILE, &lim)) {
3501 max = lim.rlim_cur;
3502 } else {
3503 min = lim.rlim_cur;
3504 }
3505 } while (min + 1 < max);
3506 }
3507 }
Ryan Dahlb6c5cf62010-05-04 17:41:563508 // Ignore SIGPIPE
Tom Hughesf61b1102010-10-12 21:01:583509 RegisterSignalHandler(SIGPIPE, SIG_IGN);
Geir Haugec61b0e92014-03-31 07:52:033510 RegisterSignalHandler(SIGINT, SignalExit, true);
3511 RegisterSignalHandler(SIGTERM, SignalExit, true);
Fedor Indutny8e29ce92013-07-31 18:07:293512#endif // __POSIX__
Ryan Dahlb6c5cf62010-05-04 17:41:563513
Fedor Indutny6a610a02014-10-04 14:44:393514 if (!use_debug_agent) {
Ben Noordhuis74a82152012-02-03 15:32:003515 RegisterDebugSignalHandler();
Ben Noordhuis74a82152012-02-03 15:32:003516 }
Ben Noordhuis5866f1a2011-12-09 18:02:333517}
Ben Noordhuis356992f2011-11-22 16:10:093518
Ben Noordhuis5866f1a2011-12-09 18:02:333519
Ben Noordhuise4a8d262012-04-21 05:13:253520struct AtExitCallback {
3521 AtExitCallback* next_;
3522 void (*cb_)(void* arg);
3523 void* arg_;
3524};
3525
3526static AtExitCallback* at_exit_functions_;
3527
3528
Ben Noordhuis756b6222013-08-10 22:26:113529// TODO(bnoordhuis) Turn into per-context event.
3530void RunAtExit(Environment* env) {
Ben Noordhuise4a8d262012-04-21 05:13:253531 AtExitCallback* p = at_exit_functions_;
3532 at_exit_functions_ = NULL;
3533
3534 while (p) {
3535 AtExitCallback* q = p->next_;
3536 p->cb_(p->arg_);
3537 delete p;
3538 p = q;
3539 }
3540}
3541
3542
3543void AtExit(void (*cb)(void* arg), void* arg) {
3544 AtExitCallback* p = new AtExitCallback;
3545 p->cb_ = cb;
3546 p->arg_ = arg;
3547 p->next_ = at_exit_functions_;
3548 at_exit_functions_ = p;
3549}
3550
3551
Ben Noordhuisa2eeb432013-10-07 13:39:393552void EmitBeforeExit(Environment* env) {
3553 Context::Scope context_scope(env->context());
3554 HandleScope handle_scope(env->isolate());
3555 Local<Object> process_object = env->process_object();
3556 Local<String> exit_code = FIXED_ONE_BYTE_STRING(env->isolate(), "exitCode");
3557 Local<Value> args[] = {
3558 FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
3559 process_object->Get(exit_code)->ToInteger()
3560 };
3561 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3562}
3563
3564
Fedor Indutnye57ab7b2014-01-18 22:49:333565int EmitExit(Environment* env) {
Ben Noordhuis5866f1a2011-12-09 18:02:333566 // process.emit('exit')
Ben Noordhuis756b6222013-08-10 22:26:113567 HandleScope handle_scope(env->isolate());
Ben Noordhuis27f115d2013-11-11 09:53:003568 Context::Scope context_scope(env->context());
Ben Noordhuis756b6222013-08-10 22:26:113569 Local<Object> process_object = env->process_object();
Fedor Indutny75adde02014-02-21 13:02:423570 process_object->Set(env->exiting_string(), True(env->isolate()));
isaacsa5dba822013-09-06 23:46:353571
Fedor Indutny75adde02014-02-21 13:02:423572 Handle<String> exitCode = env->exit_code_string();
Rasmus Christian Pedersen734fb492014-09-18 12:10:533573 int code = process_object->Get(exitCode)->Int32Value();
isaacsa5dba822013-09-06 23:46:353574
Ben Noordhuisf674b092013-08-07 19:50:413575 Local<Value> args[] = {
Fedor Indutny75adde02014-02-21 13:02:423576 env->exit_string(),
Fedor Indutnyce04c722014-03-13 16:38:143577 Integer::New(env->isolate(), code)
Ben Noordhuisf674b092013-08-07 19:50:413578 };
isaacsa5dba822013-09-06 23:46:353579
Ben Noordhuis756b6222013-08-10 22:26:113580 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
Fedor Indutnyc0d81f92014-02-09 10:40:573581
3582 // Reload exit code, it may be changed by `emit('exit')`
Rasmus Christian Pedersen734fb492014-09-18 12:10:533583 return process_object->Get(exitCode)->Int32Value();
Ben Noordhuis756b6222013-08-10 22:26:113584}
3585
3586
Fedor Indutny6a610a02014-10-04 14:44:393587// Just a convenience method
Ben Noordhuis756b6222013-08-10 22:26:113588Environment* CreateEnvironment(Isolate* isolate,
Dean McNameeda30c002014-07-09 11:36:503589 Handle<Context> context,
Ben Noordhuis756b6222013-08-10 22:26:113590 int argc,
3591 const char* const* argv,
3592 int exec_argc,
3593 const char* const* exec_argv) {
Fedor Indutny6a610a02014-10-04 14:44:393594 Environment* env;
3595 Context::Scope context_scope(context);
3596
3597 env = CreateEnvironment(isolate,
3598 uv_default_loop(),
3599 context,
3600 argc,
3601 argv,
3602 exec_argc,
3603 exec_argv);
3604
3605 LoadEnvironment(env);
3606
3607 return env;
3608}
3609
3610
3611static void HandleCloseCb(uv_handle_t* handle) {
3612 Environment* env = reinterpret_cast<Environment*>(handle->data);
3613 env->FinishHandleCleanup(handle);
3614}
3615
3616
3617static void HandleCleanup(Environment* env,
3618 uv_handle_t* handle,
3619 void* arg) {
3620 handle->data = env;
3621 uv_close(handle, HandleCloseCb);
3622}
3623
3624
3625Environment* CreateEnvironment(Isolate* isolate,
3626 uv_loop_t* loop,
3627 Handle<Context> context,
3628 int argc,
3629 const char* const* argv,
3630 int exec_argc,
3631 const char* const* exec_argv) {
Ben Noordhuis756b6222013-08-10 22:26:113632 HandleScope handle_scope(isolate);
3633
Ben Noordhuis756b6222013-08-10 22:26:113634 Context::Scope context_scope(context);
Fedor Indutny6a610a02014-10-04 14:44:393635 Environment* env = Environment::New(context, loop);
Ben Noordhuis756b6222013-08-10 22:26:113636
Vladimir Kurchatkin8dc6be12014-09-22 16:19:503637 isolate->SetAutorunMicrotasks(false);
3638
Ben Noordhuis756b6222013-08-10 22:26:113639 uv_check_init(env->event_loop(), env->immediate_check_handle());
3640 uv_unref(
3641 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
Fedor Indutny6a610a02014-10-04 14:44:393642
Ben Noordhuis756b6222013-08-10 22:26:113643 uv_idle_init(env->event_loop(), env->immediate_idle_handle());
3644
Ben Noordhuis57231d52013-10-02 04:37:443645 // Inform V8's CPU profiler when we're idle. The profiler is sampling-based
3646 // but not all samples are created equal; mark the wall clock time spent in
3647 // epoll_wait() and friends so profiling tools can filter it out. The samples
3648 // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
Ben Noordhuis57231d52013-10-02 04:37:443649 // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
3650 // probably fortify in the API contract, namely that the last started prepare
3651 // or check watcher runs first. It's not 100% foolproof; if an add-on starts
3652 // a prepare or check watcher after us, any samples attributed to its callback
3653 // will be recorded with state=IDLE.
3654 uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
Ben Noordhuis58729f12013-10-03 17:27:513655 uv_check_init(env->event_loop(), env->idle_check_handle());
Ben Noordhuis57231d52013-10-02 04:37:443656 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
Ben Noordhuis57231d52013-10-02 04:37:443657 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
3658
Fedor Indutny6a610a02014-10-04 14:44:393659 // Register handle cleanups
3660 env->RegisterHandleCleanup(
3661 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()),
3662 HandleCleanup,
3663 NULL);
3664 env->RegisterHandleCleanup(
3665 reinterpret_cast<uv_handle_t*>(env->immediate_idle_handle()),
3666 HandleCleanup,
3667 NULL);
3668 env->RegisterHandleCleanup(
3669 reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()),
3670 HandleCleanup,
3671 NULL);
3672 env->RegisterHandleCleanup(
3673 reinterpret_cast<uv_handle_t*>(env->idle_check_handle()),
3674 HandleCleanup,
3675 NULL);
3676
Ben Noordhuis9566fe82013-10-03 08:45:323677 if (v8_is_profiling) {
Ben Noordhuis58729f12013-10-03 17:27:513678 StartProfilerIdleNotifier(env);
Ben Noordhuis9566fe82013-10-03 08:45:323679 }
3680
Fedor Indutnyce04c722014-03-13 16:38:143681 Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
Ben Noordhuisf6496262013-10-03 09:03:463682 process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
3683
3684 Local<Object> process_object = process_template->GetFunction()->NewInstance();
3685 env->set_process_object(process_object);
3686
3687 SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
Ben Noordhuisf6496262013-10-03 09:03:463688
Ben Noordhuis756b6222013-08-10 22:26:113689 return env;
Ben Noordhuis5866f1a2011-12-09 18:02:333690}
3691
Micheil Smith19fd5302012-03-05 17:53:153692
Ben Noordhuis185c5152013-09-02 14:42:013693int Start(int argc, char** argv) {
Felix Geisendörfer0da4c672014-01-20 08:47:193694 const char* replaceInvalid = getenv("NODE_INVALID_UTF8");
3695
3696 if (replaceInvalid == NULL)
3697 WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8;
3698
Ben Noordhuis4234bcc2013-10-16 00:54:243699#if !defined(_WIN32)
3700 // Try hard not to lose SIGUSR1 signals during the bootstrap process.
3701 InstallEarlyDebugSignalHandler();
3702#endif
3703
Ben Noordhuis185c5152013-09-02 14:42:013704 assert(argc > 0);
Micheil Smith19fd5302012-03-05 17:53:153705
Ben Noordhuis185c5152013-09-02 14:42:013706 // Hack around with the argv pointer. Used for process.title = "blah".
Ben Noordhuis1a979982012-03-15 22:10:323707 argv = uv_setup_args(argc, argv);
3708
Ben Noordhuis185c5152013-09-02 14:42:013709 // This needs to run *before* V8::Initialize(). The const_cast is not
3710 // optional, in case you're wondering.
3711 int exec_argc;
3712 const char** exec_argv;
3713 Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
Ben Noordhuis5866f1a2011-12-09 18:02:333714
Ben Noordhuis7ac23912013-09-20 20:01:493715#if HAVE_OPENSSL
3716 // V8 on Windows doesn't have a good source of entropy. Seed it from
3717 // OpenSSL's pool.
3718 V8::SetEntropySource(crypto::EntropySource);
3719#endif
3720
Fedor Indutny50839a02014-10-10 22:17:033721 V8::InitializePlatform(new Platform(4));
3722
Fedor Indutnye57ab7b2014-01-18 22:49:333723 int code;
Ben Noordhuis75ea5662013-09-23 12:27:263724 V8::Initialize();
Fedor Indutny50839a02014-10-10 22:17:033725
3726 // Fetch a reference to the main isolate, so we have a reference to it
3727 // even when we need it to access it from another (debugger) thread.
3728 node_isolate = Isolate::New();
Marcel Laverdetc33d3172012-05-04 22:29:423729 {
Trevor Norris0bba5902013-03-18 20:54:003730 Locker locker(node_isolate);
Ben Noordhuis437c2f42014-08-19 17:28:063731 Isolate::Scope isolate_scope(node_isolate);
Dean McNameeda30c002014-07-09 11:36:503732 HandleScope handle_scope(node_isolate);
3733 Local<Context> context = Context::New(node_isolate);
3734 Environment* env = CreateEnvironment(
Fedor Indutny6a610a02014-10-04 14:44:393735 node_isolate,
3736 uv_default_loop(),
3737 context,
3738 argc,
3739 argv,
3740 exec_argc,
3741 exec_argv);
3742 Context::Scope context_scope(context);
Fedor Indutny5596f932014-02-28 13:25:283743
Fedor Indutny6a610a02014-10-04 14:44:393744 // Start debug agent when argv has --debug
3745 if (use_debug_agent)
3746 StartDebug(env, debug_wait_connect);
3747
3748 LoadEnvironment(env);
3749
3750 // Enable debugger
3751 if (use_debug_agent)
3752 EnableDebug(env);
3753
3754 bool more;
3755 do {
3756 more = uv_run(env->event_loop(), UV_RUN_ONCE);
3757 if (more == false) {
3758 EmitBeforeExit(env);
3759
3760 // Emit `beforeExit` if the loop became alive either after emitting
3761 // event, or after running some callbacks.
3762 more = uv_loop_alive(env->event_loop());
3763 if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
3764 more = true;
3765 }
3766 } while (more == true);
3767 code = EmitExit(env);
3768 RunAtExit(env);
3769
Ben Noordhuis756b6222013-08-10 22:26:113770 env->Dispose();
3771 env = NULL;
Marcel Laverdetc33d3172012-05-04 22:29:423772 }
3773
Ben Noordhuis6f952842014-05-22 23:08:273774 CHECK_NE(node_isolate, NULL);
3775 node_isolate->Dispose();
3776 node_isolate = NULL;
Ryan27b268b2009-06-17 13:05:443777 V8::Dispose();
Igor Zinkovskya58b6432011-07-07 20:54:303778
Ben Noordhuis185c5152013-09-02 14:42:013779 delete[] exec_argv;
3780 exec_argv = NULL;
Micheil Smith19fd5302012-03-05 17:53:153781
Fedor Indutnye57ab7b2014-01-18 22:49:333782 return code;
Ryan19478ed2009-03-03 00:56:153783}
Ryan Dahl124fbed2010-09-19 20:13:573784
3785
3786} // namespace node