blob: 68862f1072ba5b2b434623122ab4402dac91650f [file] [log] [blame]
Ben Noordhuisff4a9d32012-03-09 23:11:111#include "node.h"
Ben Noordhuis02cab972013-07-31 21:16:082#include "node_buffer.h"
3#include "node_constants.h"
4#include "node_file.h"
5#include "node_http_parser.h"
6#include "node_javascript.h"
Ben Noordhuis02cab972013-07-31 21:16:087#include "node_version.h"
Fedor Indutny50839a02014-10-10 22:17:038#include "node_v8_platform.h"
Ben Noordhuis02cab972013-07-31 21:16:089
10#if defined HAVE_PERFCTR
11#include "node_counters.h"
12#endif
13
14#if HAVE_OPENSSL
15#include "node_crypto.h"
16#endif
17
Steven R. Loomisac2857b2014-09-05 05:03:2418#if defined(NODE_HAVE_I18N_SUPPORT)
19#include "node_i18n.h"
20#endif
21
Ben Noordhuisc4def502013-10-28 19:18:5922#if defined HAVE_DTRACE || defined HAVE_ETW
Ben Noordhuis02cab972013-07-31 21:16:0823#include "node_dtrace.h"
24#endif
25
Bert Belder22d03c92012-08-06 23:48:1526#include "ares.h"
Trevor Norrisefa62fd2013-09-24 21:12:1127#include "async-wrap.h"
28#include "async-wrap-inl.h"
Ben Noordhuis756b6222013-08-10 22:26:1129#include "env.h"
30#include "env-inl.h"
Ben Noordhuis02cab972013-07-31 21:16:0831#include "handle_wrap.h"
32#include "req_wrap.h"
33#include "string_bytes.h"
Timothy J Fontaine1a09da62014-06-10 23:36:0434#include "util.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1135#include "uv.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1136#include "v8-debug.h"
Ben Noordhuis57231d52013-10-02 04:37:4437#include "v8-profiler.h"
Ben Noordhuis02cab972013-07-31 21:16:0838#include "zlib.h"
Ryan Dahl4635ed72010-03-11 20:40:1939
Ben Noordhuis02cab972013-07-31 21:16:0840#include <errno.h>
41#include <limits.h> // PATH_MAX
Bert Beldere0f47be2011-01-17 23:22:3642#include <locale.h>
Bert Belder9cec08e2011-05-23 23:42:2243#include <signal.h>
Ryan19478ed2009-03-03 00:56:1544#include <stdio.h>
Ryan34a6f102009-05-28 12:47:1645#include <stdlib.h>
Ryan Dahlc90e44e2010-05-10 23:38:4746#include <string.h>
Ben Noordhuis02cab972013-07-31 21:16:0847#include <sys/types.h>
48
49#if defined(_MSC_VER)
Peter Bright13d6a1f2011-08-06 04:23:2550#include <direct.h>
Peter Brightb9d77772011-08-11 01:45:5651#include <io.h>
Ben Noordhuis02cab972013-07-31 21:16:0852#include <process.h>
Ben Noordhuis02cab972013-07-31 21:16:0853#define strcasecmp _stricmp
54#define getpid _getpid
Peter Brightb9d77772011-08-11 01:45:5655#define umask _umask
56typedef int mode_t;
Ben Noordhuis02cab972013-07-31 21:16:0857#else
Ben Noordhuis68200542013-10-02 10:17:5758#include <sys/resource.h> // getrlimit, setrlimit
Ben Noordhuis02cab972013-07-31 21:16:0859#include <unistd.h> // setuid, getuid
Peter Bright13d6a1f2011-08-06 04:23:2560#endif
Ryane02b71e2009-03-03 23:31:3761
Linus Mårtensson5e4e8ec2013-05-08 12:10:0762#if defined(__POSIX__) && !defined(__ANDROID__)
Ben Noordhuis02cab972013-07-31 21:16:0863#include <pwd.h> // getpwnam()
64#include <grp.h> // getgrnam()
Bert Beldera177d602010-11-25 00:02:5565#endif
66
Fedor Indutny8e29ce92013-07-31 18:07:2967#ifdef __APPLE__
Ben Noordhuis02cab972013-07-31 21:16:0868#include <crt_externs.h>
69#define environ (*_NSGetEnviron())
Fedor Indutny8e29ce92013-07-31 18:07:2970#elif !defined(_MSC_VER)
Ryan3e4fc9f2009-09-10 14:48:3871extern char **environ;
Fedor Indutny8e29ce92013-07-31 18:07:2972#endif
Ryan3e4fc9f2009-09-10 14:48:3873
Ryand6c9d312009-09-11 14:02:2974namespace node {
75
Ben Noordhuis110a9cd2013-07-03 02:23:4476using v8::Array;
Ben Noordhuis0693d222013-06-29 06:16:2577using v8::ArrayBuffer;
Ben Noordhuis110a9cd2013-07-03 02:23:4478using v8::Boolean;
79using v8::Context;
Fedor Indutnyce04c722014-03-13 16:38:1480using v8::EscapableHandleScope;
Ben Noordhuis110a9cd2013-07-03 02:23:4481using v8::Exception;
82using v8::Function;
83using v8::FunctionCallbackInfo;
84using v8::FunctionTemplate;
Ben Noordhuis511af4d2013-07-30 19:28:4385using v8::Handle;
Ben Noordhuis110a9cd2013-07-03 02:23:4486using v8::HandleScope;
87using v8::HeapStatistics;
88using v8::Integer;
89using v8::Isolate;
Ben Noordhuis511af4d2013-07-30 19:28:4390using v8::Local;
Ben Noordhuis110a9cd2013-07-03 02:23:4491using v8::Locker;
92using v8::Message;
93using v8::Number;
94using v8::Object;
95using v8::ObjectTemplate;
Ben Noordhuis110a9cd2013-07-03 02:23:4496using v8::PropertyCallbackInfo;
Ben Noordhuis511af4d2013-07-30 19:28:4397using v8::String;
Ben Noordhuis110a9cd2013-07-03 02:23:4498using v8::TryCatch;
99using v8::Uint32;
100using v8::V8;
101using v8::Value;
Trevor Norrisbdc2ea42014-10-08 08:34:46102using v8::kExternalUint32Array;
Ben Noordhuis110a9cd2013-07-03 02:23:44103
Ben Noordhuis74a82152012-02-03 15:32:00104static bool print_eval = false;
Nathan Rajlichfeaa8a42012-03-21 07:05:25105static bool force_repl = false;
isaacs5b399292012-06-21 18:42:33106static bool trace_deprecation = false;
isaacs5038f402013-03-06 01:46:37107static bool throw_deprecation = false;
Ben Noordhuis2d82cdf2014-10-22 01:29:32108static const char* eval_string = nullptr;
Ben Noordhuis74a82152012-02-03 15:32:00109static bool use_debug_agent = false;
110static bool debug_wait_connect = false;
Fedor Indutny8e29ce92013-07-31 18:07:29111static int debug_port = 5858;
Ben Noordhuis9566fe82013-10-03 08:45:32112static bool v8_is_profiling = false;
Thorsten Lorenz0fe7a0d2014-09-15 17:00:22113static bool node_is_initialized = false;
Keith M Wesolowski76b98462013-12-17 00:00:44114static node_module* modpending;
115static node_module* modlist_builtin;
Thorsten Lorenz0fe7a0d2014-09-15 17:00:22116static node_module* modlist_linked;
Keith M Wesolowski76b98462013-12-17 00:00:44117static node_module* modlist_addon;
Ben Noordhuis74a82152012-02-03 15:32:00118
Steven R. Loomisac2857b2014-09-05 05:03:24119#if defined(NODE_HAVE_I18N_SUPPORT)
120// Path to ICU data (for i18n / Intl)
Ben Noordhuis2d82cdf2014-10-22 01:29:32121static const char* icu_data_dir = nullptr;
Steven R. Loomisac2857b2014-09-05 05:03:24122#endif
123
isaacs48c3d202012-06-21 19:20:23124// used by C++ modules as well
125bool no_deprecation = false;
126
Ben Noordhuis74a82152012-02-03 15:32:00127// process-relative uptime base, initialized at start-up
128static double prog_start_time;
Ben Noordhuisca363cf2013-10-15 21:32:18129static bool debugger_running;
Ben Noordhuis5d0816b2013-01-06 22:06:48130static uv_async_t dispatch_debug_messages_async;
131
Ben Noordhuis2d82cdf2014-10-22 01:29:32132static Isolate* node_isolate = nullptr;
Ben Noordhuis5d0816b2013-01-06 22:06:48133
Felix Geisendörfer0da4c672014-01-20 08:47:19134int WRITE_UTF8_FLAGS = v8::String::HINT_MANY_WRITES_EXPECTED |
135 v8::String::NO_NULL_TERMINATION;
Ryan Dahlf80cc692010-01-06 09:17:58136
Ben Noordhuis0693d222013-06-29 06:16:25137class ArrayBufferAllocator : public ArrayBuffer::Allocator {
Fedor Indutny8e29ce92013-07-31 18:07:29138 public:
Ben Noordhuis0693d222013-06-29 06:16:25139 // Impose an upper limit to avoid out of memory errors that bring down
140 // the process.
141 static const size_t kMaxLength = 0x3fffffff;
142 static ArrayBufferAllocator the_singleton;
Ben Noordhuis5ab87db2014-10-22 02:53:26143 virtual ~ArrayBufferAllocator() = default;
Ben Noordhuis9f5800a2014-10-22 02:26:25144 virtual void* Allocate(size_t length) override;
145 virtual void* AllocateUninitialized(size_t length) override;
146 virtual void Free(void* data, size_t length) override;
Fedor Indutny8e29ce92013-07-31 18:07:29147 private:
Ben Noordhuis5ab87db2014-10-22 02:53:26148 ArrayBufferAllocator() = default;
Ben Noordhuisc038dcc2014-10-22 02:33:01149 DISALLOW_COPY_AND_ASSIGN(ArrayBufferAllocator);
Ben Noordhuis0693d222013-06-29 06:16:25150};
151
152ArrayBufferAllocator ArrayBufferAllocator::the_singleton;
153
154
155void* ArrayBufferAllocator::Allocate(size_t length) {
Fedor Indutny2bc30f22013-10-16 16:57:26156 if (length > kMaxLength)
Ben Noordhuis2d82cdf2014-10-22 01:29:32157 return nullptr;
Trevor Norris72225392013-12-10 01:11:38158 char* data = new char[length];
159 memset(data, 0, length);
160 return data;
Ben Noordhuis0693d222013-06-29 06:16:25161}
162
163
Ben Noordhuisef4a35b2013-10-22 22:17:45164void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
165 if (length > kMaxLength)
Ben Noordhuis2d82cdf2014-10-22 01:29:32166 return nullptr;
Ben Noordhuisef4a35b2013-10-22 22:17:45167 return new char[length];
168}
169
170
171void ArrayBufferAllocator::Free(void* data, size_t length) {
Ben Noordhuis0693d222013-06-29 06:16:25172 delete[] static_cast<char*>(data);
173}
174
175
Saúl Ibarra Corretgé42b93432014-03-12 23:08:29176static void CheckImmediate(uv_check_t* handle) {
Ben Noordhuis756b6222013-08-10 22:26:11177 Environment* env = Environment::from_immediate_check_handle(handle);
Fedor Indutny75adde02014-02-21 13:02:42178 HandleScope scope(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:11179 Context::Scope context_scope(env->context());
180 MakeCallback(env, env->process_object(), env->immediate_callback_string());
Shigeki Ohtsucd372512013-02-06 02:13:02181}
182
183
Saúl Ibarra Corretgé42b93432014-03-12 23:08:29184static void IdleImmediateDummy(uv_idle_t* handle) {
Ben Noordhuis756b6222013-08-10 22:26:11185 // Do nothing. Only for maintaining event loop.
Ben Noordhuis2d82cdf2014-10-22 01:29:32186 // TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
Shigeki Ohtsucd372512013-02-06 02:13:02187}
188
189
Ryan Dahlc9e27b12010-04-23 00:53:45190static inline const char *errno_string(int errorno) {
191#define ERRNO_CASE(e) case e: return #e;
192 switch (errorno) {
Ryan Dahlc9e27b12010-04-23 00:53:45193#ifdef EACCES
194 ERRNO_CASE(EACCES);
195#endif
196
197#ifdef EADDRINUSE
198 ERRNO_CASE(EADDRINUSE);
199#endif
200
201#ifdef EADDRNOTAVAIL
202 ERRNO_CASE(EADDRNOTAVAIL);
203#endif
204
205#ifdef EAFNOSUPPORT
206 ERRNO_CASE(EAFNOSUPPORT);
207#endif
208
209#ifdef EAGAIN
210 ERRNO_CASE(EAGAIN);
Ryan Dahl9b2aac62010-04-28 19:58:00211#endif
212
213#ifdef EWOULDBLOCK
214# if EAGAIN != EWOULDBLOCK
Ryan Dahlc9e27b12010-04-23 00:53:45215 ERRNO_CASE(EWOULDBLOCK);
216# endif
217#endif
218
219#ifdef EALREADY
220 ERRNO_CASE(EALREADY);
221#endif
222
223#ifdef EBADF
224 ERRNO_CASE(EBADF);
225#endif
226
227#ifdef EBADMSG
228 ERRNO_CASE(EBADMSG);
229#endif
230
231#ifdef EBUSY
232 ERRNO_CASE(EBUSY);
233#endif
234
235#ifdef ECANCELED
236 ERRNO_CASE(ECANCELED);
237#endif
238
239#ifdef ECHILD
240 ERRNO_CASE(ECHILD);
241#endif
242
243#ifdef ECONNABORTED
244 ERRNO_CASE(ECONNABORTED);
245#endif
246
247#ifdef ECONNREFUSED
248 ERRNO_CASE(ECONNREFUSED);
249#endif
250
251#ifdef ECONNRESET
252 ERRNO_CASE(ECONNRESET);
253#endif
254
255#ifdef EDEADLK
256 ERRNO_CASE(EDEADLK);
257#endif
258
259#ifdef EDESTADDRREQ
260 ERRNO_CASE(EDESTADDRREQ);
261#endif
262
263#ifdef EDOM
264 ERRNO_CASE(EDOM);
265#endif
266
267#ifdef EDQUOT
268 ERRNO_CASE(EDQUOT);
269#endif
270
271#ifdef EEXIST
272 ERRNO_CASE(EEXIST);
273#endif
274
275#ifdef EFAULT
276 ERRNO_CASE(EFAULT);
277#endif
278
279#ifdef EFBIG
280 ERRNO_CASE(EFBIG);
281#endif
282
283#ifdef EHOSTUNREACH
284 ERRNO_CASE(EHOSTUNREACH);
285#endif
286
287#ifdef EIDRM
288 ERRNO_CASE(EIDRM);
289#endif
290
291#ifdef EILSEQ
292 ERRNO_CASE(EILSEQ);
293#endif
294
295#ifdef EINPROGRESS
296 ERRNO_CASE(EINPROGRESS);
297#endif
298
299#ifdef EINTR
300 ERRNO_CASE(EINTR);
301#endif
302
303#ifdef EINVAL
304 ERRNO_CASE(EINVAL);
305#endif
306
307#ifdef EIO
308 ERRNO_CASE(EIO);
309#endif
310
311#ifdef EISCONN
312 ERRNO_CASE(EISCONN);
313#endif
314
315#ifdef EISDIR
316 ERRNO_CASE(EISDIR);
317#endif
318
319#ifdef ELOOP
320 ERRNO_CASE(ELOOP);
321#endif
322
323#ifdef EMFILE
324 ERRNO_CASE(EMFILE);
325#endif
326
327#ifdef EMLINK
328 ERRNO_CASE(EMLINK);
329#endif
330
331#ifdef EMSGSIZE
332 ERRNO_CASE(EMSGSIZE);
333#endif
334
335#ifdef EMULTIHOP
336 ERRNO_CASE(EMULTIHOP);
337#endif
338
339#ifdef ENAMETOOLONG
340 ERRNO_CASE(ENAMETOOLONG);
341#endif
342
343#ifdef ENETDOWN
344 ERRNO_CASE(ENETDOWN);
345#endif
346
347#ifdef ENETRESET
348 ERRNO_CASE(ENETRESET);
349#endif
350
351#ifdef ENETUNREACH
352 ERRNO_CASE(ENETUNREACH);
353#endif
354
355#ifdef ENFILE
356 ERRNO_CASE(ENFILE);
357#endif
358
359#ifdef ENOBUFS
360 ERRNO_CASE(ENOBUFS);
361#endif
362
363#ifdef ENODATA
364 ERRNO_CASE(ENODATA);
365#endif
366
367#ifdef ENODEV
368 ERRNO_CASE(ENODEV);
369#endif
370
371#ifdef ENOENT
372 ERRNO_CASE(ENOENT);
373#endif
374
375#ifdef ENOEXEC
376 ERRNO_CASE(ENOEXEC);
377#endif
378
Ryan Dahlc9e27b12010-04-23 00:53:45379#ifdef ENOLINK
380 ERRNO_CASE(ENOLINK);
381#endif
382
Ryan Dahl3bb21b52010-04-28 22:07:15383#ifdef ENOLCK
384# if ENOLINK != ENOLCK
385 ERRNO_CASE(ENOLCK);
386# endif
387#endif
388
Ryan Dahlc9e27b12010-04-23 00:53:45389#ifdef ENOMEM
390 ERRNO_CASE(ENOMEM);
391#endif
392
393#ifdef ENOMSG
394 ERRNO_CASE(ENOMSG);
395#endif
396
397#ifdef ENOPROTOOPT
398 ERRNO_CASE(ENOPROTOOPT);
399#endif
400
401#ifdef ENOSPC
402 ERRNO_CASE(ENOSPC);
403#endif
404
405#ifdef ENOSR
406 ERRNO_CASE(ENOSR);
407#endif
408
409#ifdef ENOSTR
410 ERRNO_CASE(ENOSTR);
411#endif
412
413#ifdef ENOSYS
414 ERRNO_CASE(ENOSYS);
415#endif
416
417#ifdef ENOTCONN
418 ERRNO_CASE(ENOTCONN);
419#endif
420
421#ifdef ENOTDIR
422 ERRNO_CASE(ENOTDIR);
423#endif
424
425#ifdef ENOTEMPTY
426 ERRNO_CASE(ENOTEMPTY);
427#endif
428
429#ifdef ENOTSOCK
430 ERRNO_CASE(ENOTSOCK);
431#endif
432
433#ifdef ENOTSUP
434 ERRNO_CASE(ENOTSUP);
435#else
436# ifdef EOPNOTSUPP
437 ERRNO_CASE(EOPNOTSUPP);
438# endif
439#endif
440
441#ifdef ENOTTY
442 ERRNO_CASE(ENOTTY);
443#endif
444
445#ifdef ENXIO
446 ERRNO_CASE(ENXIO);
447#endif
448
449
450#ifdef EOVERFLOW
451 ERRNO_CASE(EOVERFLOW);
452#endif
453
454#ifdef EPERM
455 ERRNO_CASE(EPERM);
456#endif
457
458#ifdef EPIPE
459 ERRNO_CASE(EPIPE);
460#endif
461
462#ifdef EPROTO
463 ERRNO_CASE(EPROTO);
464#endif
465
466#ifdef EPROTONOSUPPORT
467 ERRNO_CASE(EPROTONOSUPPORT);
468#endif
469
470#ifdef EPROTOTYPE
471 ERRNO_CASE(EPROTOTYPE);
472#endif
473
474#ifdef ERANGE
475 ERRNO_CASE(ERANGE);
476#endif
477
478#ifdef EROFS
479 ERRNO_CASE(EROFS);
480#endif
481
482#ifdef ESPIPE
483 ERRNO_CASE(ESPIPE);
484#endif
485
486#ifdef ESRCH
487 ERRNO_CASE(ESRCH);
488#endif
489
490#ifdef ESTALE
491 ERRNO_CASE(ESTALE);
492#endif
493
494#ifdef ETIME
495 ERRNO_CASE(ETIME);
496#endif
497
498#ifdef ETIMEDOUT
499 ERRNO_CASE(ETIMEDOUT);
500#endif
501
502#ifdef ETXTBSY
503 ERRNO_CASE(ETXTBSY);
504#endif
505
506#ifdef EXDEV
507 ERRNO_CASE(EXDEV);
508#endif
509
510 default: return "";
511 }
512}
513
Felix Geisendörferf8a3cf92010-04-28 13:04:08514const char *signo_string(int signo) {
515#define SIGNO_CASE(e) case e: return #e;
516 switch (signo) {
Felix Geisendörferf8a3cf92010-04-28 13:04:08517#ifdef SIGHUP
518 SIGNO_CASE(SIGHUP);
519#endif
520
521#ifdef SIGINT
522 SIGNO_CASE(SIGINT);
523#endif
524
525#ifdef SIGQUIT
526 SIGNO_CASE(SIGQUIT);
527#endif
528
529#ifdef SIGILL
530 SIGNO_CASE(SIGILL);
531#endif
532
533#ifdef SIGTRAP
534 SIGNO_CASE(SIGTRAP);
535#endif
536
537#ifdef SIGABRT
538 SIGNO_CASE(SIGABRT);
539#endif
540
541#ifdef SIGIOT
542# if SIGABRT != SIGIOT
543 SIGNO_CASE(SIGIOT);
544# endif
545#endif
546
547#ifdef SIGBUS
548 SIGNO_CASE(SIGBUS);
549#endif
550
551#ifdef SIGFPE
552 SIGNO_CASE(SIGFPE);
553#endif
554
555#ifdef SIGKILL
556 SIGNO_CASE(SIGKILL);
557#endif
558
559#ifdef SIGUSR1
560 SIGNO_CASE(SIGUSR1);
561#endif
562
563#ifdef SIGSEGV
564 SIGNO_CASE(SIGSEGV);
565#endif
566
567#ifdef SIGUSR2
568 SIGNO_CASE(SIGUSR2);
569#endif
570
571#ifdef SIGPIPE
572 SIGNO_CASE(SIGPIPE);
573#endif
574
575#ifdef SIGALRM
576 SIGNO_CASE(SIGALRM);
577#endif
578
579 SIGNO_CASE(SIGTERM);
Bert Belderdcc35082010-11-25 00:04:31580
581#ifdef SIGCHLD
Felix Geisendörferf8a3cf92010-04-28 13:04:08582 SIGNO_CASE(SIGCHLD);
Bert Belderdcc35082010-11-25 00:04:31583#endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08584
585#ifdef SIGSTKFLT
586 SIGNO_CASE(SIGSTKFLT);
587#endif
588
589
590#ifdef SIGCONT
591 SIGNO_CASE(SIGCONT);
592#endif
593
594#ifdef SIGSTOP
595 SIGNO_CASE(SIGSTOP);
596#endif
597
598#ifdef SIGTSTP
599 SIGNO_CASE(SIGTSTP);
600#endif
601
Bert Belder600a6462012-08-20 21:59:21602#ifdef SIGBREAK
603 SIGNO_CASE(SIGBREAK);
604#endif
605
Felix Geisendörferf8a3cf92010-04-28 13:04:08606#ifdef SIGTTIN
607 SIGNO_CASE(SIGTTIN);
608#endif
609
610#ifdef SIGTTOU
611 SIGNO_CASE(SIGTTOU);
612#endif
613
614#ifdef SIGURG
615 SIGNO_CASE(SIGURG);
616#endif
617
618#ifdef SIGXCPU
619 SIGNO_CASE(SIGXCPU);
620#endif
621
622#ifdef SIGXFSZ
623 SIGNO_CASE(SIGXFSZ);
624#endif
625
626#ifdef SIGVTALRM
627 SIGNO_CASE(SIGVTALRM);
628#endif
629
630#ifdef SIGPROF
631 SIGNO_CASE(SIGPROF);
632#endif
633
634#ifdef SIGWINCH
635 SIGNO_CASE(SIGWINCH);
636#endif
637
638#ifdef SIGIO
639 SIGNO_CASE(SIGIO);
640#endif
641
642#ifdef SIGPOLL
Ryan Dahl3bb21b52010-04-28 22:07:15643# if SIGPOLL != SIGIO
Felix Geisendörferf8a3cf92010-04-28 13:04:08644 SIGNO_CASE(SIGPOLL);
Ryan Dahl3bb21b52010-04-28 22:07:15645# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08646#endif
647
648#ifdef SIGLOST
649 SIGNO_CASE(SIGLOST);
650#endif
651
652#ifdef SIGPWR
Raffaele Senab3b81d62010-06-09 04:08:05653# if SIGPWR != SIGLOST
Felix Geisendörferf8a3cf92010-04-28 13:04:08654 SIGNO_CASE(SIGPWR);
Raffaele Senab3b81d62010-06-09 04:08:05655# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08656#endif
657
658#ifdef SIGSYS
659 SIGNO_CASE(SIGSYS);
660#endif
661
Felix Geisendörferf8a3cf92010-04-28 13:04:08662 default: return "";
663 }
664}
665
Ryan Dahlc9e27b12010-04-23 00:53:45666
Fedor Indutny7b9771f2014-03-17 20:46:40667// Convenience methods
668
669
670void ThrowError(v8::Isolate* isolate, const char* errmsg) {
671 Environment::GetCurrent(isolate)->ThrowError(errmsg);
672}
673
674
675void ThrowTypeError(v8::Isolate* isolate, const char* errmsg) {
676 Environment::GetCurrent(isolate)->ThrowTypeError(errmsg);
677}
678
679
680void ThrowRangeError(v8::Isolate* isolate, const char* errmsg) {
681 Environment::GetCurrent(isolate)->ThrowRangeError(errmsg);
682}
683
684
685void ThrowErrnoException(v8::Isolate* isolate,
686 int errorno,
687 const char* syscall,
688 const char* message,
689 const char* path) {
690 Environment::GetCurrent(isolate)->ThrowErrnoException(errorno,
691 syscall,
692 message,
693 path);
694}
695
696
697void ThrowUVException(v8::Isolate* isolate,
698 int errorno,
699 const char* syscall,
700 const char* message,
701 const char* path) {
702 Environment::GetCurrent(isolate)->ThrowErrnoException(errorno,
703 syscall,
704 message,
705 path);
706}
707
708
Fedor Indutny75adde02014-02-21 13:02:42709Local<Value> ErrnoException(Isolate* isolate,
710 int errorno,
Ryan Dahlc9e27b12010-04-23 00:53:45711 const char *syscall,
visionmedia45948e02010-05-14 14:52:49712 const char *msg,
713 const char *path) {
Fedor Indutny75adde02014-02-21 13:02:42714 Environment* env = Environment::GetCurrent(isolate);
Ben Noordhuis756b6222013-08-10 22:26:11715
visionmedia45948e02010-05-14 14:52:49716 Local<Value> e;
Fedor Indutny75adde02014-02-21 13:02:42717 Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
Ben Noordhuis2d82cdf2014-10-22 01:29:32718 if (msg == nullptr || msg[0] == '\0') {
Bert Belder2ce09612011-01-17 21:47:59719 msg = strerror(errorno);
Bert Belder2ce09612011-01-17 21:47:59720 }
Fedor Indutny75adde02014-02-21 13:02:42721 Local<String> message = OneByteString(env->isolate(), msg);
Ryan Dahlc9e27b12010-04-23 00:53:45722
Ben Noordhuisf674b092013-08-07 19:50:41723 Local<String> cons1 =
Fedor Indutny75adde02014-02-21 13:02:42724 String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
Ryan Dahlc9e27b12010-04-23 00:53:45725 Local<String> cons2 = String::Concat(cons1, message);
726
visionmedia45948e02010-05-14 14:52:49727 if (path) {
Ben Noordhuisf674b092013-08-07 19:50:41728 Local<String> cons3 =
Fedor Indutny75adde02014-02-21 13:02:42729 String::Concat(cons2, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
Ben Noordhuisf674b092013-08-07 19:50:41730 Local<String> cons4 =
Fedor Indutny75adde02014-02-21 13:02:42731 String::Concat(cons3, String::NewFromUtf8(env->isolate(), path));
Ben Noordhuisf674b092013-08-07 19:50:41732 Local<String> cons5 =
Fedor Indutny75adde02014-02-21 13:02:42733 String::Concat(cons4, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
visionmedia45948e02010-05-14 14:52:49734 e = Exception::Error(cons5);
735 } else {
736 e = Exception::Error(cons2);
737 }
738
Trevor Norrisd5533862015-01-07 21:29:58739 Local<Object> obj = e->ToObject(env->isolate());
Fedor Indutnyce04c722014-03-13 16:38:14740 obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
Ben Noordhuis756b6222013-08-10 22:26:11741 obj->Set(env->code_string(), estring);
visionmedia45948e02010-05-14 14:52:49742
Ben Noordhuis2d82cdf2014-10-22 01:29:32743 if (path != nullptr) {
Fedor Indutny75adde02014-02-21 13:02:42744 obj->Set(env->path_string(), String::NewFromUtf8(env->isolate(), path));
Ben Noordhuis756b6222013-08-10 22:26:11745 }
746
Ben Noordhuis2d82cdf2014-10-22 01:29:32747 if (syscall != nullptr) {
Fedor Indutny75adde02014-02-21 13:02:42748 obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
Ben Noordhuis756b6222013-08-10 22:26:11749 }
750
Ryan Dahlc9e27b12010-04-23 00:53:45751 return e;
752}
753
754
Bert Belder823a4432011-12-01 23:02:51755// hack alert! copy of ErrnoException, tuned for uv errors
Fedor Indutny75adde02014-02-21 13:02:42756Local<Value> UVException(Isolate* isolate,
757 int errorno,
Bert Belder823a4432011-12-01 23:02:51758 const char *syscall,
759 const char *msg,
760 const char *path) {
Fedor Indutny75adde02014-02-21 13:02:42761 Environment* env = Environment::GetCurrent(isolate);
Bert Belder823a4432011-12-01 23:02:51762
763 if (!msg || !msg[0])
Ben Noordhuisca9eb712013-07-18 21:18:50764 msg = uv_strerror(errorno);
Bert Belder823a4432011-12-01 23:02:51765
Fedor Indutny75adde02014-02-21 13:02:42766 Local<String> estring = OneByteString(env->isolate(), uv_err_name(errorno));
767 Local<String> message = OneByteString(env->isolate(), msg);
Ben Noordhuisf674b092013-08-07 19:50:41768 Local<String> cons1 =
Fedor Indutny75adde02014-02-21 13:02:42769 String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
Bert Belder823a4432011-12-01 23:02:51770 Local<String> cons2 = String::Concat(cons1, message);
771
772 Local<Value> e;
773
774 Local<String> path_str;
775
776 if (path) {
777#ifdef _WIN32
778 if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
Fedor Indutny75adde02014-02-21 13:02:42779 path_str = String::Concat(FIXED_ONE_BYTE_STRING(env->isolate(), "\\\\"),
780 String::NewFromUtf8(env->isolate(), path + 8));
Bert Belder823a4432011-12-01 23:02:51781 } else if (strncmp(path, "\\\\?\\", 4) == 0) {
Fedor Indutny75adde02014-02-21 13:02:42782 path_str = String::NewFromUtf8(env->isolate(), path + 4);
Bert Belder823a4432011-12-01 23:02:51783 } else {
Fedor Indutny75adde02014-02-21 13:02:42784 path_str = String::NewFromUtf8(env->isolate(), path);
Bert Belder823a4432011-12-01 23:02:51785 }
786#else
Fedor Indutny75adde02014-02-21 13:02:42787 path_str = String::NewFromUtf8(env->isolate(), path);
Bert Belder823a4432011-12-01 23:02:51788#endif
789
Ben Noordhuisf674b092013-08-07 19:50:41790 Local<String> cons3 =
Fedor Indutny75adde02014-02-21 13:02:42791 String::Concat(cons2, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
Ben Noordhuisf674b092013-08-07 19:50:41792 Local<String> cons4 =
793 String::Concat(cons3, path_str);
794 Local<String> cons5 =
Fedor Indutny75adde02014-02-21 13:02:42795 String::Concat(cons4, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
Bert Belder823a4432011-12-01 23:02:51796 e = Exception::Error(cons5);
797 } else {
798 e = Exception::Error(cons2);
799 }
800
Trevor Norrisd5533862015-01-07 21:29:58801 Local<Object> obj = e->ToObject(env->isolate());
Fedor Indutny8e29ce92013-07-31 18:07:29802 // TODO(piscisaureus) errno should probably go
Fedor Indutnyce04c722014-03-13 16:38:14803 obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
Ben Noordhuis756b6222013-08-10 22:26:11804 obj->Set(env->code_string(), estring);
805
Ben Noordhuis2d82cdf2014-10-22 01:29:32806 if (path != nullptr) {
Ben Noordhuis756b6222013-08-10 22:26:11807 obj->Set(env->path_string(), path_str);
808 }
809
Ben Noordhuis2d82cdf2014-10-22 01:29:32810 if (syscall != nullptr) {
Fedor Indutny75adde02014-02-21 13:02:42811 obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
Ben Noordhuis756b6222013-08-10 22:26:11812 }
813
Bert Belder823a4432011-12-01 23:02:51814 return e;
815}
816
817
Ben Noordhuis8f6c5872014-10-11 19:48:25818// Look up environment variable unless running as setuid root.
819inline const char* secure_getenv(const char* key) {
820#ifndef _WIN32
821 if (getuid() != geteuid() || getgid() != getegid())
Ben Noordhuis2d82cdf2014-10-22 01:29:32822 return nullptr;
Ben Noordhuis8f6c5872014-10-11 19:48:25823#endif
824 return getenv(key);
825}
826
827
Bert Belder6ee73a22011-11-04 15:10:48828#ifdef _WIN32
Igor Zinkovsky500c8f42011-12-15 20:36:05829// Does about the same as strerror(),
830// but supports all windows error messages
Alexis Campailla93f3b642014-08-05 13:33:16831static const char *winapi_strerror(const int errorno, bool* must_free) {
Ben Noordhuis2d82cdf2014-10-22 01:29:32832 char *errmsg = nullptr;
Igor Zinkovsky500c8f42011-12-15 20:36:05833
834 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
Ben Noordhuis2d82cdf2014-10-22 01:29:32835 FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
836 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
Igor Zinkovsky500c8f42011-12-15 20:36:05837
838 if (errmsg) {
Alexis Campailla93f3b642014-08-05 13:33:16839 *must_free = true;
840
Igor Zinkovsky500c8f42011-12-15 20:36:05841 // Remove trailing newlines
842 for (int i = strlen(errmsg) - 1;
843 i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
844 errmsg[i] = '\0';
845 }
846
847 return errmsg;
848 } else {
849 // FormatMessage failed
Alexis Campailla93f3b642014-08-05 13:33:16850 *must_free = false;
Igor Zinkovsky500c8f42011-12-15 20:36:05851 return "Unknown error";
852 }
853}
854
855
Alexis Campailla440b9e22014-02-24 18:55:27856Local<Value> WinapiErrnoException(Isolate* isolate,
Fedor Indutny75adde02014-02-21 13:02:42857 int errorno,
Bert Belder829735e2011-11-04 15:23:02858 const char* syscall,
859 const char* msg,
860 const char* path) {
Alexis Campailla440b9e22014-02-24 18:55:27861 Environment* env = Environment::GetCurrent(isolate);
Bert Belder6ee73a22011-11-04 15:10:48862 Local<Value> e;
Alexis Campailla93f3b642014-08-05 13:33:16863 bool must_free = false;
Bert Belder829735e2011-11-04 15:23:02864 if (!msg || !msg[0]) {
Alexis Campailla93f3b642014-08-05 13:33:16865 msg = winapi_strerror(errorno, &must_free);
Bert Belder6ee73a22011-11-04 15:10:48866 }
Fedor Indutny75adde02014-02-21 13:02:42867 Local<String> message = OneByteString(env->isolate(), msg);
Bert Belder6ee73a22011-11-04 15:10:48868
Bert Belder6ee73a22011-11-04 15:10:48869 if (path) {
Ben Noordhuisf674b092013-08-07 19:50:41870 Local<String> cons1 =
Alexis Campailla440b9e22014-02-24 18:55:27871 String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
Ben Noordhuisf674b092013-08-07 19:50:41872 Local<String> cons2 =
Alexis Campailla440b9e22014-02-24 18:55:27873 String::Concat(cons1, String::NewFromUtf8(isolate, path));
Ben Noordhuisf674b092013-08-07 19:50:41874 Local<String> cons3 =
Alexis Campailla440b9e22014-02-24 18:55:27875 String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
Bert Belder6ee73a22011-11-04 15:10:48876 e = Exception::Error(cons3);
877 } else {
878 e = Exception::Error(message);
879 }
880
Trevor Norrisd5533862015-01-07 21:29:58881 Local<Object> obj = e->ToObject(env->isolate());
Fedor Indutnyce04c722014-03-13 16:38:14882 obj->Set(env->errno_string(), Integer::New(isolate, errorno));
Bert Belder6ee73a22011-11-04 15:10:48883
Ben Noordhuis2d82cdf2014-10-22 01:29:32884 if (path != nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:27885 obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
Ben Noordhuis756b6222013-08-10 22:26:11886 }
887
Ben Noordhuis2d82cdf2014-10-22 01:29:32888 if (syscall != nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:27889 obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
Ben Noordhuis756b6222013-08-10 22:26:11890 }
891
Alexis Campailla93f3b642014-08-05 13:33:16892 if (must_free)
893 LocalFree((HLOCAL)msg);
894
Bert Belder6ee73a22011-11-04 15:10:48895 return e;
896}
897#endif
898
899
Trevor Norris828f1452014-01-09 19:11:40900void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:55901 Environment* env = Environment::GetCurrent(args);
Trevor Norris828f1452014-01-09 19:11:40902
903 if (env->using_domains())
904 return;
905 env->set_using_domains(true);
906
Fedor Indutny75adde02014-02-21 13:02:42907 HandleScope scope(env->isolate());
Trevor Norris828f1452014-01-09 19:11:40908 Local<Object> process_object = env->process_object();
909
Fedor Indutny75adde02014-02-21 13:02:42910 Local<String> tick_callback_function_key = env->tick_domain_cb_string();
Trevor Norris828f1452014-01-09 19:11:40911 Local<Function> tick_callback_function =
912 process_object->Get(tick_callback_function_key).As<Function>();
913
914 if (!tick_callback_function->IsFunction()) {
915 fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
916 abort();
917 }
918
Fedor Indutny75adde02014-02-21 13:02:42919 process_object->Set(env->tick_callback_string(), tick_callback_function);
Trevor Norris828f1452014-01-09 19:11:40920 env->set_tick_callback_function(tick_callback_function);
921
Ben Noordhuis5fdff382014-10-11 14:52:07922 CHECK(args[0]->IsArray());
923 CHECK(args[1]->IsObject());
Trevor Norris828f1452014-01-09 19:11:40924
925 env->set_domain_array(args[0].As<Array>());
926
927 Local<Object> domain_flag_obj = args[1].As<Object>();
928 Environment::DomainFlag* domain_flag = env->domain_flag();
929 domain_flag_obj->SetIndexedPropertiesToExternalArrayData(
930 domain_flag->fields(),
Trevor Norrisbdc2ea42014-10-08 08:34:46931 kExternalUint32Array,
Trevor Norris828f1452014-01-09 19:11:40932 domain_flag->fields_count());
933
934 // Do a little housekeeping.
935 env->process_object()->Delete(
936 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse"));
937}
938
Vladimir Kurchatkin30bd7b62014-09-04 16:02:04939void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
940 args.GetIsolate()->RunMicrotasks();
941}
942
Trevor Norris828f1452014-01-09 19:11:40943
Trevor Norrisefa62fd2013-09-24 21:12:11944void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:55945 Environment* env = Environment::GetCurrent(args);
Trevor Norrisefa62fd2013-09-24 21:12:11946
Ben Noordhuis5fdff382014-10-11 14:52:07947 CHECK(args[0]->IsObject());
948 CHECK(args[1]->IsFunction());
949 CHECK(args[2]->IsObject());
Trevor Norrisefa62fd2013-09-24 21:12:11950
951 // Values use to cross communicate with processNextTick.
952 Local<Object> tick_info_obj = args[0].As<Object>();
953 tick_info_obj->SetIndexedPropertiesToExternalArrayData(
954 env->tick_info()->fields(),
Trevor Norrisbdc2ea42014-10-08 08:34:46955 kExternalUint32Array,
Trevor Norrisefa62fd2013-09-24 21:12:11956 env->tick_info()->fields_count());
957
958 env->set_tick_callback_function(args[1].As<Function>());
959
Ben Noordhuisd3c317e2014-10-13 13:19:55960 env->SetMethod(args[2].As<Object>(), "runMicrotasks", RunMicrotasks);
Vladimir Kurchatkin30bd7b62014-09-04 16:02:04961
Trevor Norrisefa62fd2013-09-24 21:12:11962 // Do a little housekeeping.
963 env->process_object()->Delete(
964 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick"));
Trevor Norris3f5d5842013-08-07 00:01:44965}
966
967
Ben Noordhuis756b6222013-08-10 22:26:11968Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:16969 Handle<Value> recv,
Ben Noordhuis756b6222013-08-10 22:26:11970 const Handle<Function> callback,
971 int argc,
972 Handle<Value> argv[]) {
Trevor Norrisefa62fd2013-09-24 21:12:11973 // If you hit this assertion, you forgot to enter the v8::Context first.
Ben Noordhuis5fdff382014-10-11 14:52:07974 CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
Trevor Norrisefa62fd2013-09-24 21:12:11975
976 Local<Object> process = env->process_object();
Trevor Norrisa1da0242014-12-09 04:24:59977 Local<Object> object, domain;
Trevor Norrisb9e60322014-12-09 04:10:44978 bool has_async_queue = false;
Trevor Norrisa1da0242014-12-09 04:24:59979 bool has_domain = false;
980
Trevor Norrisb9e60322014-12-09 04:10:44981 if (recv->IsObject()) {
982 object = recv.As<Object>();
983 Local<Value> async_queue_v = object->Get(env->async_queue_string());
984 if (async_queue_v->IsObject())
985 has_async_queue = true;
986 }
987
Trevor Norrisa1da0242014-12-09 04:24:59988 if (env->using_domains()) {
989 CHECK(recv->IsObject());
Trevor Norrisa1da0242014-12-09 04:24:59990 Local<Value> domain_v = object->Get(env->domain_string());
991 has_domain = domain_v->IsObject();
992 if (has_domain) {
993 domain = domain_v.As<Object>();
994 if (domain->Get(env->disposed_string())->IsTrue())
995 return Undefined(env->isolate());
996 }
997 }
Trevor Norrisefa62fd2013-09-24 21:12:11998
Trevor Norris86c07452013-02-07 01:26:18999 TryCatch try_catch;
Miroslav Bajtosc16963b2013-06-17 19:19:591000 try_catch.SetVerbose(true);
Trevor Norris86c07452013-02-07 01:26:181001
Trevor Norrisa1da0242014-12-09 04:24:591002 if (has_domain) {
1003 Local<Value> enter_v = domain->Get(env->enter_string());
1004 if (enter_v->IsFunction()) {
1005 enter_v.As<Function>()->Call(domain, 0, nullptr);
1006 if (try_catch.HasCaught())
1007 return Undefined(env->isolate());
1008 }
1009 }
1010
Trevor Norrisb9e60322014-12-09 04:10:441011 if (has_async_queue) {
1012 try_catch.SetVerbose(false);
1013 env->async_hooks_pre_function()->Call(object, 0, nullptr);
1014 if (try_catch.HasCaught())
1015 FatalError("node:;MakeCallback", "pre hook threw");
1016 try_catch.SetVerbose(true);
1017 }
1018
Ben Noordhuis1f2f3fa2014-01-27 02:58:161019 Local<Value> ret = callback->Call(recv, argc, argv);
isaacs10ce3d12012-04-13 23:27:231020
Trevor Norrisb9e60322014-12-09 04:10:441021 if (has_async_queue) {
1022 try_catch.SetVerbose(false);
1023 env->async_hooks_post_function()->Call(object, 0, nullptr);
1024 if (try_catch.HasCaught())
1025 FatalError("node::MakeCallback", "post hook threw");
1026 try_catch.SetVerbose(true);
1027 }
1028
Trevor Norrisa1da0242014-12-09 04:24:591029 if (has_domain) {
1030 Local<Value> exit_v = domain->Get(env->exit_string());
1031 if (exit_v->IsFunction()) {
1032 exit_v.As<Function>()->Call(domain, 0, nullptr);
1033 if (try_catch.HasCaught())
1034 return Undefined(env->isolate());
1035 }
1036 }
1037 env->tick_callback_function()->Call(process, 0, nullptr);
1038 CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
1039
isaacs10ce3d12012-04-13 23:27:231040 if (try_catch.HasCaught()) {
Fedor Indutny75adde02014-02-21 13:02:421041 return Undefined(env->isolate());
Ryan Dahl650a3082011-05-28 20:44:031042 }
isaacsac1aadd2012-04-13 23:34:481043
Ben Noordhuis756b6222013-08-10 22:26:111044 Environment::TickInfo* tick_info = env->tick_info();
1045
Trevor Norrisefa62fd2013-09-24 21:12:111046 if (tick_info->in_tick()) {
Trevor Norris6a5a7b02013-07-30 22:06:451047 return ret;
1048 }
1049
Ben Noordhuis756b6222013-08-10 22:26:111050 if (tick_info->length() == 0) {
Vladimir Kurchatkin8dc6be12014-09-22 16:19:501051 env->isolate()->RunMicrotasks();
1052 }
1053
1054 if (tick_info->length() == 0) {
Ben Noordhuis756b6222013-08-10 22:26:111055 tick_info->set_index(0);
Trevor Norrisa0867e12013-03-17 04:59:471056 return ret;
Trevor Norrisec420002013-02-13 14:30:061057 }
1058
Trevor Norris4b84e422013-08-27 18:30:061059 tick_info->set_in_tick(true);
1060
Trevor Norris86c07452013-02-07 01:26:181061 // process nextTicks after call
Ben Noordhuis2d82cdf2014-10-22 01:29:321062 env->tick_callback_function()->Call(process, 0, nullptr);
Trevor Norris86c07452013-02-07 01:26:181063
Trevor Norris4b84e422013-08-27 18:30:061064 tick_info->set_in_tick(false);
1065
Trevor Norris86c07452013-02-07 01:26:181066 if (try_catch.HasCaught()) {
Trevor Norris4b84e422013-08-27 18:30:061067 tick_info->set_last_threw(true);
Fedor Indutny75adde02014-02-21 13:02:421068 return Undefined(env->isolate());
Trevor Norris86c07452013-02-07 01:26:181069 }
1070
Trevor Norrisa0867e12013-03-17 04:59:471071 return ret;
1072}
1073
1074
Ben Noordhuis7a3f7782013-08-15 17:22:441075// Internal only.
Ben Noordhuis756b6222013-08-10 22:26:111076Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161077 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111078 uint32_t index,
1079 int argc,
1080 Handle<Value> argv[]) {
Trevor Norrisa1da0242014-12-09 04:24:591081 Local<Value> cb_v = recv->Get(index);
1082 CHECK(cb_v->IsFunction());
1083 return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
Ben Noordhuis7a3f7782013-08-15 17:22:441084}
1085
1086
Ben Noordhuis756b6222013-08-10 22:26:111087Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161088 Handle<Object> recv,
1089 Handle<String> symbol,
Ben Noordhuis756b6222013-08-10 22:26:111090 int argc,
1091 Handle<Value> argv[]) {
Trevor Norrisa1da0242014-12-09 04:24:591092 Local<Value> cb_v = recv->Get(symbol);
1093 CHECK(cb_v->IsFunction());
1094 return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
Trevor Norris86c07452013-02-07 01:26:181095}
1096
1097
Ben Noordhuis756b6222013-08-10 22:26:111098Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161099 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111100 const char* method,
1101 int argc,
1102 Handle<Value> argv[]) {
Fedor Indutny75adde02014-02-21 13:02:421103 Local<String> method_string = OneByteString(env->isolate(), method);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161104 return MakeCallback(env, recv, method_string, argc, argv);
Ben Noordhuis756b6222013-08-10 22:26:111105}
Trevor Norris86c07452013-02-07 01:26:181106
Ben Noordhuis756b6222013-08-10 22:26:111107
Fedor Indutny75adde02014-02-21 13:02:421108Handle<Value> MakeCallback(Isolate* isolate,
1109 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111110 const char* method,
1111 int argc,
1112 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141113 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161114 Local<Context> context = recv->CreationContext();
Ben Noordhuis756b6222013-08-10 22:26:111115 Environment* env = Environment::GetCurrent(context);
1116 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141117 return handle_scope.Escape(
1118 Local<Value>::New(isolate, MakeCallback(env, recv, method, argc, argv)));
Ben Noordhuis756b6222013-08-10 22:26:111119}
1120
1121
Fedor Indutny75adde02014-02-21 13:02:421122Handle<Value> MakeCallback(Isolate* isolate,
1123 Handle<Object> recv,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161124 Handle<String> symbol,
Ben Noordhuis756b6222013-08-10 22:26:111125 int argc,
1126 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141127 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161128 Local<Context> context = recv->CreationContext();
Ben Noordhuis756b6222013-08-10 22:26:111129 Environment* env = Environment::GetCurrent(context);
1130 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141131 return handle_scope.Escape(
1132 Local<Value>::New(isolate, MakeCallback(env, recv, symbol, argc, argv)));
Ben Noordhuis756b6222013-08-10 22:26:111133}
1134
1135
Fedor Indutny75adde02014-02-21 13:02:421136Handle<Value> MakeCallback(Isolate* isolate,
1137 Handle<Object> recv,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161138 Handle<Function> callback,
Ben Noordhuis756b6222013-08-10 22:26:111139 int argc,
1140 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141141 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161142 Local<Context> context = recv->CreationContext();
Trevor Norris828f1452014-01-09 19:11:401143 Environment* env = Environment::GetCurrent(context);
1144 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141145 return handle_scope.Escape(Local<Value>::New(
1146 isolate,
1147 MakeCallback(env, recv.As<Value>(), callback, argc, argv)));
Ben Noordhuis1f2f3fa2014-01-27 02:58:161148}
1149
1150
Fedor Indutny75adde02014-02-21 13:02:421151enum encoding ParseEncoding(Isolate* isolate,
1152 Handle<Value> encoding_v,
1153 enum encoding _default) {
1154 HandleScope scope(isolate);
Ryan Dahl07792af2009-09-21 10:27:221155
Fedor Indutny2bc30f22013-10-16 16:57:261156 if (!encoding_v->IsString())
1157 return _default;
Ryan Dahl07792af2009-09-21 10:27:221158
Trevor Norriscbf76c12015-01-07 22:13:351159 node::Utf8Value encoding(isolate, encoding_v);
Ryan Dahl07792af2009-09-21 10:27:221160
1161 if (strcasecmp(*encoding, "utf8") == 0) {
1162 return UTF8;
Ryan Dahl2b994d92009-10-06 08:45:181163 } else if (strcasecmp(*encoding, "utf-8") == 0) {
1164 return UTF8;
Ryan Dahl07792af2009-09-21 10:27:221165 } else if (strcasecmp(*encoding, "ascii") == 0) {
1166 return ASCII;
Ben Noordhuis95638c92010-07-28 12:20:231167 } else if (strcasecmp(*encoding, "base64") == 0) {
1168 return BASE64;
Konstantin Käfer9e101f22011-02-06 20:49:521169 } else if (strcasecmp(*encoding, "ucs2") == 0) {
1170 return UCS2;
1171 } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1172 return UCS2;
koichikfbb0ee62012-10-02 14:57:381173 } else if (strcasecmp(*encoding, "utf16le") == 0) {
1174 return UCS2;
1175 } else if (strcasecmp(*encoding, "utf-16le") == 0) {
1176 return UCS2;
Ryan Dahl07792af2009-09-21 10:27:221177 } else if (strcasecmp(*encoding, "binary") == 0) {
1178 return BINARY;
Fedor Indutny63ff4492012-09-12 20:35:591179 } else if (strcasecmp(*encoding, "buffer") == 0) {
1180 return BUFFER;
isaacs0aa1a8a2011-02-20 01:29:011181 } else if (strcasecmp(*encoding, "hex") == 0) {
1182 return HEX;
Ryan Dahl07792af2009-09-21 10:27:221183 } else if (strcasecmp(*encoding, "raw") == 0) {
isaacs5b399292012-06-21 18:42:331184 if (!no_deprecation) {
1185 fprintf(stderr, "'raw' (array of integers) has been removed. "
1186 "Use 'binary'.\n");
1187 }
Ryan Dahl07792af2009-09-21 10:27:221188 return BINARY;
1189 } else if (strcasecmp(*encoding, "raws") == 0) {
isaacs5b399292012-06-21 18:42:331190 if (!no_deprecation) {
1191 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1192 "Please update your code.\n");
1193 }
Ryan Dahl07792af2009-09-21 10:27:221194 return BINARY;
1195 } else {
1196 return _default;
1197 }
1198}
1199
Fedor Indutny75adde02014-02-21 13:02:421200Local<Value> Encode(Isolate* isolate,
Ben Noordhuis56fde662014-12-10 16:33:561201 const char* buf,
Fedor Indutny75adde02014-02-21 13:02:421202 size_t len,
1203 enum encoding encoding) {
Ben Noordhuis56fde662014-12-10 16:33:561204 CHECK_NE(encoding, UCS2);
1205 return StringBytes::Encode(isolate, buf, len, encoding);
1206}
1207
1208Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1209 return StringBytes::Encode(isolate, buf, len);
Ryan21a1b042009-09-09 13:51:491210}
1211
Ryand6c9d312009-09-11 14:02:291212// Returns -1 if the handle was not valid for decoding
Fedor Indutny75adde02014-02-21 13:02:421213ssize_t DecodeBytes(Isolate* isolate,
1214 Handle<Value> val,
1215 enum encoding encoding) {
1216 HandleScope scope(isolate);
Ryan21a1b042009-09-09 13:51:491217
1218 if (val->IsArray()) {
isaacsa3753b42012-05-16 23:32:371219 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1220 "Use 'binary'.\n");
Ben Noordhuis5fdff382014-10-11 14:52:071221 UNREACHABLE();
Ryan Dahl07792af2009-09-21 10:27:221222 return -1;
Ryan21a1b042009-09-09 13:51:491223 }
1224
Fedor Indutny75adde02014-02-21 13:02:421225 return StringBytes::Size(isolate, val, encoding);
Ryan21a1b042009-09-09 13:51:491226}
1227
Ryan21a1b042009-09-09 13:51:491228// Returns number of bytes written.
Fedor Indutny75adde02014-02-21 13:02:421229ssize_t DecodeWrite(Isolate* isolate,
1230 char* buf,
Ryan Dahl53530e92010-04-02 21:55:281231 size_t buflen,
Fedor Indutny75adde02014-02-21 13:02:421232 Handle<Value> val,
Ryand6c9d312009-09-11 14:02:291233 enum encoding encoding) {
Ben Noordhuis2d82cdf2014-10-22 01:29:321234 return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
Ryan21a1b042009-09-09 13:51:491235}
1236
Fedor Indutnyf1de13b2014-02-05 16:38:331237void AppendExceptionLine(Environment* env,
1238 Handle<Value> er,
1239 Handle<Message> message) {
1240 if (message.IsEmpty())
Fedor Indutny2bc30f22013-10-16 16:57:261241 return;
isaacsb3cf3f32012-07-28 21:00:271242
Fedor Indutnyf1de13b2014-02-05 16:38:331243 HandleScope scope(env->isolate());
1244 Local<Object> err_obj;
1245 if (!er.IsEmpty() && er->IsObject()) {
1246 err_obj = er.As<Object>();
Ryan Dahlcdf5d912011-10-11 20:41:331247
Fedor Indutnyf1de13b2014-02-05 16:38:331248 // Do it only once per message
1249 if (!err_obj->GetHiddenValue(env->processed_string()).IsEmpty())
1250 return;
1251 err_obj->SetHiddenValue(env->processed_string(), True(env->isolate()));
Ryan Dahl8e6dd522010-01-15 18:45:041252 }
Fedor Indutnyf1de13b2014-02-05 16:38:331253
Ben Noordhuis8ba39b02014-11-12 14:29:341254 char arrow[1024];
Fedor Indutnyf1de13b2014-02-05 16:38:331255
1256 // Print (filename):(line number): (message).
Trevor Norriscbf76c12015-01-07 22:13:351257 node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
Fedor Indutnyf1de13b2014-02-05 16:38:331258 const char* filename_string = *filename;
1259 int linenum = message->GetLineNumber();
1260 // Print line of source code.
Trevor Norriscbf76c12015-01-07 22:13:351261 node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
Fedor Indutnyf1de13b2014-02-05 16:38:331262 const char* sourceline_string = *sourceline;
1263
1264 // Because of how node modules work, all scripts are wrapped with a
1265 // "function (module, exports, __filename, ...) {"
1266 // to provide script local variables.
1267 //
1268 // When reporting errors on the first line of a script, this wrapper
1269 // function is leaked to the user. There used to be a hack here to
1270 // truncate off the first 62 characters, but it caused numerous other
1271 // problems when vm.runIn*Context() methods were used for non-module
1272 // code.
1273 //
1274 // If we ever decide to re-instate such a hack, the following steps
1275 // must be taken:
1276 //
1277 // 1. Pass a flag around to say "this code was wrapped"
1278 // 2. Update the stack frame output so that it is also correct.
1279 //
1280 // It would probably be simpler to add a line rather than add some
1281 // number of characters to the first line, since V8 truncates the
1282 // sourceline to 78 characters, and we end up not providing very much
1283 // useful debugging info to the user if we remove 62 characters.
1284
1285 int start = message->GetStartColumn();
1286 int end = message->GetEndColumn();
1287
1288 int off = snprintf(arrow,
1289 sizeof(arrow),
1290 "%s:%i\n%s\n",
1291 filename_string,
1292 linenum,
1293 sourceline_string);
Ben Noordhuis5fdff382014-10-11 14:52:071294 CHECK_GE(off, 0);
Fedor Indutnyf1de13b2014-02-05 16:38:331295
1296 // Print wavy underline (GetUnderline is deprecated).
1297 for (int i = 0; i < start; i++) {
Yazhong Liu6b09f9c2014-06-25 13:18:501298 if (sourceline_string[i] == '\0' ||
1299 static_cast<size_t>(off) >= sizeof(arrow)) {
1300 break;
1301 }
Ben Noordhuis5fdff382014-10-11 14:52:071302 CHECK_LT(static_cast<size_t>(off), sizeof(arrow));
Fedor Indutnyf1de13b2014-02-05 16:38:331303 arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1304 }
1305 for (int i = start; i < end; i++) {
Yazhong Liu6b09f9c2014-06-25 13:18:501306 if (sourceline_string[i] == '\0' ||
1307 static_cast<size_t>(off) >= sizeof(arrow)) {
1308 break;
1309 }
Ben Noordhuis5fdff382014-10-11 14:52:071310 CHECK_LT(static_cast<size_t>(off), sizeof(arrow));
Fedor Indutnyf1de13b2014-02-05 16:38:331311 arrow[off++] = '^';
1312 }
Ben Noordhuis5fdff382014-10-11 14:52:071313 CHECK_LE(static_cast<size_t>(off - 1), sizeof(arrow) - 1);
Fedor Indutnyf1de13b2014-02-05 16:38:331314 arrow[off++] = '\n';
1315 arrow[off] = '\0';
1316
1317 Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1318 Local<Value> msg;
1319 Local<Value> stack;
1320
1321 // Allocation failed, just print it out
1322 if (arrow_str.IsEmpty() || err_obj.IsEmpty() || !err_obj->IsNativeError())
1323 goto print;
1324
1325 msg = err_obj->Get(env->message_string());
1326 stack = err_obj->Get(env->stack_string());
1327
1328 if (msg.IsEmpty() || stack.IsEmpty())
1329 goto print;
1330
1331 err_obj->Set(env->message_string(),
Trevor Norrisd5533862015-01-07 21:29:581332 String::Concat(arrow_str, msg->ToString(env->isolate())));
Fedor Indutnyf1de13b2014-02-05 16:38:331333 err_obj->Set(env->stack_string(),
Trevor Norrisd5533862015-01-07 21:29:581334 String::Concat(arrow_str, stack->ToString(env->isolate())));
Fedor Indutnyf1de13b2014-02-05 16:38:331335 return;
1336
1337 print:
1338 if (env->printed_error())
1339 return;
1340 env->set_printed_error(true);
1341 uv_tty_reset_mode();
1342 fprintf(stderr, "\n%s", arrow);
Ryan Dahlb57c1f52010-11-24 02:46:131343}
1344
1345
Fedor Indutnyf1de13b2014-02-05 16:38:331346static void ReportException(Environment* env,
1347 Handle<Value> er,
1348 Handle<Message> message) {
1349 HandleScope scope(env->isolate());
Ryan Dahlb57c1f52010-11-24 02:46:131350
Fedor Indutnyf1de13b2014-02-05 16:38:331351 AppendExceptionLine(env, er, message);
Ryan Dahl53a841d2009-12-29 19:20:511352
Vladimir Kurchatkin259d4492013-12-06 11:56:371353 Local<Value> trace_value;
1354
Fedor Indutnyf1de13b2014-02-05 16:38:331355 if (er->IsUndefined() || er->IsNull())
1356 trace_value = Undefined(env->isolate());
1357 else
Trevor Norrisd5533862015-01-07 21:29:581358 trace_value = er->ToObject(env->isolate())->Get(env->stack_string());
Vladimir Kurchatkin259d4492013-12-06 11:56:371359
Trevor Norriscbf76c12015-01-07 22:13:351360 node::Utf8Value trace(env->isolate(), trace_value);
Ryan Dahlda932302010-05-14 18:48:141361
isaacs8df6f9e2011-04-25 19:22:181362 // range errors have a trace member set to undefined
Miroslav Bajtosc16963b2013-06-17 19:19:591363 if (trace.length() > 0 && !trace_value->IsUndefined()) {
Ryanafd9e712009-08-31 16:22:091364 fprintf(stderr, "%s\n", *trace);
isaacse9b6b0b2010-10-02 06:22:341365 } else {
1366 // this really only happens for RangeErrors, since they're the only
isaacs8df6f9e2011-04-25 19:22:181367 // kind that won't have all this info in the trace, or when non-Error
1368 // objects are thrown manually.
Ben Noordhuisf674b092013-08-07 19:50:411369 Local<Value> message;
1370 Local<Value> name;
isaacs8df6f9e2011-04-25 19:22:181371
Ben Noordhuisf674b092013-08-07 19:50:411372 if (er->IsObject()) {
1373 Local<Object> err_obj = er.As<Object>();
Fedor Indutnyf1de13b2014-02-05 16:38:331374 message = err_obj->Get(env->message_string());
1375 name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
isaacs8df6f9e2011-04-25 19:22:181376 }
1377
Ben Noordhuisf674b092013-08-07 19:50:411378 if (message.IsEmpty() ||
1379 message->IsUndefined() ||
1380 name.IsEmpty() ||
1381 name->IsUndefined()) {
1382 // Not an error object. Just print as-is.
Trevor Norriscbf76c12015-01-07 22:13:351383 node::Utf8Value message(env->isolate(), er);
Ben Noordhuisf674b092013-08-07 19:50:411384 fprintf(stderr, "%s\n", *message);
1385 } else {
Trevor Norriscbf76c12015-01-07 22:13:351386 node::Utf8Value name_string(env->isolate(), name);
1387 node::Utf8Value message_string(env->isolate(), message);
Ben Noordhuisf674b092013-08-07 19:50:411388 fprintf(stderr, "%s: %s\n", *name_string, *message_string);
1389 }
Ryan5131e0a2009-03-09 00:23:411390 }
isaacse9b6b0b2010-10-02 06:22:341391
Ryand7e220c2009-09-09 20:35:401392 fflush(stderr);
Ryan5131e0a2009-03-09 00:23:411393}
1394
Miroslav Bajtosc16963b2013-06-17 19:19:591395
Fedor Indutnyf1de13b2014-02-05 16:38:331396static void ReportException(Environment* env, const TryCatch& try_catch) {
1397 ReportException(env, try_catch.Exception(), try_catch.Message());
Miroslav Bajtosc16963b2013-06-17 19:19:591398}
1399
1400
Ryand6c9d312009-09-11 14:02:291401// Executes a str within the current v8 context.
Fedor Indutnyf1de13b2014-02-05 16:38:331402static Local<Value> ExecuteString(Environment* env,
1403 Handle<String> source,
Ben Noordhuisc7214fe2014-03-31 13:13:371404 Handle<String> filename) {
Fedor Indutnyce04c722014-03-13 16:38:141405 EscapableHandleScope scope(env->isolate());
Ryan408526a2009-04-21 11:52:211406 TryCatch try_catch;
1407
Miroslav Bajtosc16963b2013-06-17 19:19:591408 // try_catch must be nonverbose to disable FatalException() handler,
1409 // we will handle exceptions ourself.
1410 try_catch.SetVerbose(false);
1411
Herbert Vojcikc2a06722010-04-17 15:18:151412 Local<v8::Script> script = v8::Script::Compile(source, filename);
Ryan63a9cd32009-04-15 08:08:281413 if (script.IsEmpty()) {
Fedor Indutnyf1de13b2014-02-05 16:38:331414 ReportException(env, try_catch);
isaacs95862b22013-02-27 19:23:201415 exit(3);
Ryan63a9cd32009-04-15 08:08:281416 }
1417
Ryan Dahl9f5643f2010-01-31 07:22:341418 Local<Value> result = script->Run();
Ryan63a9cd32009-04-15 08:08:281419 if (result.IsEmpty()) {
Fedor Indutnyf1de13b2014-02-05 16:38:331420 ReportException(env, try_catch);
isaacs95862b22013-02-27 19:23:201421 exit(4);
Ryan63a9cd32009-04-15 08:08:281422 }
1423
Fedor Indutnyce04c722014-03-13 16:38:141424 return scope.Escape(result);
Ryan63a9cd32009-04-15 08:08:281425}
1426
Felix Geisendörfer7371fcb2009-11-11 17:10:581427
Ben Noordhuis110a9cd2013-07-03 02:23:441428static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551429 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis5f040652012-04-28 16:45:101430
Fedor Indutnyce04c722014-03-13 16:38:141431 Local<Array> ary = Array::New(args.GetIsolate());
Ben Noordhuis2d82cdf2014-10-22 01:29:321432 QUEUE* q = nullptr;
Ben Noordhuis5f040652012-04-28 16:45:101433 int i = 0;
1434
Fedor Indutny6a610a02014-10-04 14:44:391435 QUEUE_FOREACH(q, env->req_wrap_queue()) {
Ben Noordhuis820aaf52014-05-27 21:31:311436 ReqWrap<uv_req_t>* w = ContainerOf(&ReqWrap<uv_req_t>::req_wrap_queue_, q);
Fedor Indutny2bc30f22013-10-16 16:57:261437 if (w->persistent().IsEmpty())
1438 continue;
Ben Noordhuis110a9cd2013-07-03 02:23:441439 ary->Set(i++, w->object());
Ben Noordhuis5f040652012-04-28 16:45:101440 }
1441
Ben Noordhuis110a9cd2013-07-03 02:23:441442 args.GetReturnValue().Set(ary);
Ben Noordhuis5f040652012-04-28 16:45:101443}
1444
1445
1446// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1447// implemented here for consistency with GetActiveRequests().
Ben Noordhuis110a9cd2013-07-03 02:23:441448void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551449 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis5f040652012-04-28 16:45:101450
Fedor Indutnyce04c722014-03-13 16:38:141451 Local<Array> ary = Array::New(env->isolate());
Ben Noordhuis2d82cdf2014-10-22 01:29:321452 QUEUE* q = nullptr;
Ben Noordhuis5f040652012-04-28 16:45:101453 int i = 0;
1454
Fedor Indutny75adde02014-02-21 13:02:421455 Local<String> owner_sym = env->owner_string();
Ben Noordhuise813e342012-05-15 15:24:061456
Fedor Indutny6a610a02014-10-04 14:44:391457 QUEUE_FOREACH(q, env->handle_wrap_queue()) {
Ben Noordhuis820aaf52014-05-27 21:31:311458 HandleWrap* w = ContainerOf(&HandleWrap::handle_wrap_queue_, q);
Fedor Indutny2bc30f22013-10-16 16:57:261459 if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
1460 continue;
Ben Noordhuis110a9cd2013-07-03 02:23:441461 Local<Object> object = w->object();
1462 Local<Value> owner = object->Get(owner_sym);
Fedor Indutny2bc30f22013-10-16 16:57:261463 if (owner->IsUndefined())
1464 owner = object;
Ben Noordhuis110a9cd2013-07-03 02:23:441465 ary->Set(i++, owner);
Ben Noordhuis5f040652012-04-28 16:45:101466 }
1467
Ben Noordhuis110a9cd2013-07-03 02:23:441468 args.GetReturnValue().Set(ary);
Ben Noordhuis5f040652012-04-28 16:45:101469}
1470
1471
Ben Noordhuis110a9cd2013-07-03 02:23:441472static void Abort(const FunctionCallbackInfo<Value>& args) {
Robert Mustacchi22404862011-12-15 01:02:151473 abort();
1474}
1475
1476
Ben Noordhuis110a9cd2013-07-03 02:23:441477static void Chdir(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551478 Environment* env = Environment::GetCurrent(args);
Ryan Dahlb20c3432010-02-12 05:55:081479
Brandon Beacher47fcf782009-11-03 18:13:381480 if (args.Length() != 1 || !args[0]->IsString()) {
Caitlin Potterbe2404e2015-01-09 16:38:281481 return env->ThrowTypeError("Bad argument.");
Brandon Beacher47fcf782009-11-03 18:13:381482 }
Ryan Dahlb20c3432010-02-12 05:55:081483
Trevor Norriscbf76c12015-01-07 22:13:351484 node::Utf8Value path(args.GetIsolate(), args[0]);
Ben Noordhuisca9eb712013-07-18 21:18:501485 int err = uv_chdir(*path);
1486 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421487 return env->ThrowUVException(err, "uv_chdir");
Brandon Beacher47fcf782009-11-03 18:13:381488 }
Brandon Beacher47fcf782009-11-03 18:13:381489}
1490
Bert Beldercbcf4fe2011-11-24 01:19:541491
Ben Noordhuis110a9cd2013-07-03 02:23:441492static void Cwd(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551493 Environment* env = Environment::GetCurrent(args);
Bert Beldere84edd22011-12-01 23:24:441494#ifdef _WIN32
1495 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261496 char buf[MAX_PATH * 4];
Bert Beldere84edd22011-12-01 23:24:441497#else
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261498 char buf[PATH_MAX];
Bert Beldere84edd22011-12-01 23:24:441499#endif
Michael Carter8ea6adc2009-09-01 09:39:301500
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261501 size_t cwd_len = sizeof(buf);
1502 int err = uv_cwd(buf, &cwd_len);
Ben Noordhuisca9eb712013-07-18 21:18:501503 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421504 return env->ThrowUVException(err, "uv_cwd");
Michael Carter8ea6adc2009-09-01 09:39:301505 }
Peter Griess4e3c5d82010-07-12 15:47:451506
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261507 Local<String> cwd = String::NewFromUtf8(env->isolate(),
1508 buf,
1509 String::kNormalString,
Saúl Ibarra Corretgée46cbaa2014-10-17 07:31:591510 cwd_len);
Ben Noordhuis110a9cd2013-07-03 02:23:441511 args.GetReturnValue().Set(cwd);
Michael Carter8ea6adc2009-09-01 09:39:301512}
1513
Bert Beldere84edd22011-12-01 23:24:441514
Ben Noordhuis110a9cd2013-07-03 02:23:441515static void Umask(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551516 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis110a9cd2013-07-03 02:23:441517 uint32_t old;
isaacs5f2e9092011-01-25 18:40:121518
Ryan Dahlacc120a2011-08-09 20:53:561519 if (args.Length() < 1 || args[0]->IsUndefined()) {
Rasmus Andersson374300c2010-02-27 17:18:411520 old = umask(0);
Ben Noordhuis110a9cd2013-07-03 02:23:441521 umask(static_cast<mode_t>(old));
Fedor Indutny8e29ce92013-07-31 18:07:291522 } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421523 return env->ThrowTypeError("argument must be an integer or octal string.");
isaacs5f2e9092011-01-25 18:40:121524 } else {
1525 int oct;
Fedor Indutny8e29ce92013-07-31 18:07:291526 if (args[0]->IsInt32()) {
isaacs5f2e9092011-01-25 18:40:121527 oct = args[0]->Uint32Value();
1528 } else {
1529 oct = 0;
Trevor Norriscbf76c12015-01-07 22:13:351530 node::Utf8Value str(env->isolate(), args[0]);
isaacs5f2e9092011-01-25 18:40:121531
1532 // Parse the octal string.
Timothy J Fontaine1a09da62014-06-10 23:36:041533 for (size_t i = 0; i < str.length(); i++) {
isaacs5f2e9092011-01-25 18:40:121534 char c = (*str)[i];
1535 if (c > '7' || c < '0') {
Fedor Indutny75adde02014-02-21 13:02:421536 return env->ThrowTypeError("invalid octal string");
isaacs5f2e9092011-01-25 18:40:121537 }
1538 oct *= 8;
1539 oct += c - '0';
1540 }
1541 }
1542 old = umask(static_cast<mode_t>(oct));
Friedemann Altrock0433d822009-11-22 18:52:521543 }
isaacs5f2e9092011-01-25 18:40:121544
Ben Noordhuis110a9cd2013-07-03 02:23:441545 args.GetReturnValue().Set(old);
Friedemann Altrock0433d822009-11-22 18:52:521546}
1547
Michael Cartera3860762010-02-08 06:13:101548
Linus Mårtensson5e4e8ec2013-05-08 12:10:071549#if defined(__POSIX__) && !defined(__ANDROID__)
Ryan Dahlacc120a2011-08-09 20:53:561550
Ben Noordhuis3ece1302012-12-04 05:36:231551static const uid_t uid_not_found = static_cast<uid_t>(-1);
1552static const gid_t gid_not_found = static_cast<gid_t>(-1);
1553
1554
1555static uid_t uid_by_name(const char* name) {
1556 struct passwd pwd;
1557 struct passwd* pp;
1558 char buf[8192];
Ben Noordhuis3ece1302012-12-04 05:36:231559
1560 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321561 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231562
Ben Noordhuis2d82cdf2014-10-22 01:29:321563 if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231564 return pp->pw_uid;
1565 }
1566
1567 return uid_not_found;
1568}
1569
1570
1571static char* name_by_uid(uid_t uid) {
1572 struct passwd pwd;
1573 struct passwd* pp;
1574 char buf[8192];
1575 int rc;
1576
1577 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321578 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231579
Ben Noordhuis2d82cdf2014-10-22 01:29:321580 if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1581 pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231582 return strdup(pp->pw_name);
1583 }
1584
1585 if (rc == 0) {
1586 errno = ENOENT;
1587 }
1588
Ben Noordhuis2d82cdf2014-10-22 01:29:321589 return nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231590}
1591
1592
1593static gid_t gid_by_name(const char* name) {
1594 struct group pwd;
1595 struct group* pp;
1596 char buf[8192];
Ben Noordhuis3ece1302012-12-04 05:36:231597
1598 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321599 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231600
Ben Noordhuis2d82cdf2014-10-22 01:29:321601 if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231602 return pp->gr_gid;
1603 }
1604
1605 return gid_not_found;
1606}
1607
1608
1609#if 0 // For future use.
1610static const char* name_by_gid(gid_t gid) {
1611 struct group pwd;
1612 struct group* pp;
1613 char buf[8192];
1614 int rc;
1615
1616 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321617 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231618
Ben Noordhuis2d82cdf2014-10-22 01:29:321619 if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1620 pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231621 return strdup(pp->gr_name);
1622 }
1623
1624 if (rc == 0) {
1625 errno = ENOENT;
1626 }
1627
Ben Noordhuis2d82cdf2014-10-22 01:29:321628 return nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231629}
1630#endif
1631
1632
1633static uid_t uid_by_name(Handle<Value> value) {
1634 if (value->IsUint32()) {
1635 return static_cast<uid_t>(value->Uint32Value());
1636 } else {
Trevor Norriscbf76c12015-01-07 22:13:351637 // TODO(trevnorris): Fix to not use GetCurrent().
1638 node::Utf8Value name(Isolate::GetCurrent(), value);
Ben Noordhuis3ece1302012-12-04 05:36:231639 return uid_by_name(*name);
1640 }
1641}
1642
1643
1644static gid_t gid_by_name(Handle<Value> value) {
1645 if (value->IsUint32()) {
1646 return static_cast<gid_t>(value->Uint32Value());
1647 } else {
Trevor Norriscbf76c12015-01-07 22:13:351648 // TODO(trevnorris): Fix to not use GetCurrent().
1649 node::Utf8Value name(Isolate::GetCurrent(), value);
Ben Noordhuis3ece1302012-12-04 05:36:231650 return gid_by_name(*name);
1651 }
1652}
1653
1654
Ben Noordhuis110a9cd2013-07-03 02:23:441655static void GetUid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis6df47412013-09-05 19:47:081656 // uid_t is an uint32_t on all supported platforms.
1657 args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
Michael Cartera3860762010-02-08 06:13:101658}
1659
Ryan Dahlacc120a2011-08-09 20:53:561660
Ben Noordhuis110a9cd2013-07-03 02:23:441661static void GetGid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis6df47412013-09-05 19:47:081662 // gid_t is an uint32_t on all supported platforms.
1663 args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
James Duncandf1c1e52010-02-23 22:45:021664}
1665
1666
Ben Noordhuis110a9cd2013-07-03 02:23:441667static void SetGid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551668 Environment* env = Environment::GetCurrent(args);
Ryan Dahl39943402010-03-15 19:49:401669
Ben Noordhuis3ece1302012-12-04 05:36:231670 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421671 return env->ThrowTypeError("setgid argument must be a number or a string");
James Duncandf1c1e52010-02-23 22:45:021672 }
1673
Ben Noordhuis3ece1302012-12-04 05:36:231674 gid_t gid = gid_by_name(args[0]);
Blake Mizerany8c853402010-06-30 06:12:461675
Ben Noordhuis3ece1302012-12-04 05:36:231676 if (gid == gid_not_found) {
Fedor Indutny75adde02014-02-21 13:02:421677 return env->ThrowError("setgid group id does not exist");
Peter Griess2420f072010-05-19 00:40:441678 }
1679
Ben Noordhuis3ece1302012-12-04 05:36:231680 if (setgid(gid)) {
Fedor Indutny75adde02014-02-21 13:02:421681 return env->ThrowErrnoException(errno, "setgid");
James Duncandf1c1e52010-02-23 22:45:021682 }
James Duncandf1c1e52010-02-23 22:45:021683}
Michael Cartera3860762010-02-08 06:13:101684
Ryan Dahlacc120a2011-08-09 20:53:561685
Ben Noordhuis110a9cd2013-07-03 02:23:441686static void SetUid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551687 Environment* env = Environment::GetCurrent(args);
Michael Cartera3860762010-02-08 06:13:101688
Ben Noordhuis3ece1302012-12-04 05:36:231689 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421690 return env->ThrowTypeError("setuid argument must be a number or a string");
Michael Cartera3860762010-02-08 06:13:101691 }
1692
Ben Noordhuis3ece1302012-12-04 05:36:231693 uid_t uid = uid_by_name(args[0]);
Peter Griess2420f072010-05-19 00:40:441694
Ben Noordhuis3ece1302012-12-04 05:36:231695 if (uid == uid_not_found) {
Fedor Indutny75adde02014-02-21 13:02:421696 return env->ThrowError("setuid user id does not exist");
Peter Griess2420f072010-05-19 00:40:441697 }
1698
Ben Noordhuis3ece1302012-12-04 05:36:231699 if (setuid(uid)) {
Fedor Indutny75adde02014-02-21 13:02:421700 return env->ThrowErrnoException(errno, "setuid");
Michael Cartera3860762010-02-08 06:13:101701 }
Michael Cartera3860762010-02-08 06:13:101702}
1703
Ryan Dahlacc120a2011-08-09 20:53:561704
Ben Noordhuis110a9cd2013-07-03 02:23:441705static void GetGroups(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551706 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis3ece1302012-12-04 05:36:231707
Ben Noordhuis2d82cdf2014-10-22 01:29:321708 int ngroups = getgroups(0, nullptr);
Ben Noordhuis3ece1302012-12-04 05:36:231709
1710 if (ngroups == -1) {
Fedor Indutny75adde02014-02-21 13:02:421711 return env->ThrowErrnoException(errno, "getgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231712 }
1713
1714 gid_t* groups = new gid_t[ngroups];
1715
1716 ngroups = getgroups(ngroups, groups);
1717
1718 if (ngroups == -1) {
1719 delete[] groups;
Fedor Indutny75adde02014-02-21 13:02:421720 return env->ThrowErrnoException(errno, "getgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231721 }
1722
Fedor Indutnyce04c722014-03-13 16:38:141723 Local<Array> groups_list = Array::New(env->isolate(), ngroups);
Ben Noordhuis3ece1302012-12-04 05:36:231724 bool seen_egid = false;
1725 gid_t egid = getegid();
1726
1727 for (int i = 0; i < ngroups; i++) {
Fedor Indutnyce04c722014-03-13 16:38:141728 groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
Fedor Indutny2bc30f22013-10-16 16:57:261729 if (groups[i] == egid)
1730 seen_egid = true;
Ben Noordhuis3ece1302012-12-04 05:36:231731 }
1732
1733 delete[] groups;
1734
1735 if (seen_egid == false) {
Fedor Indutnyce04c722014-03-13 16:38:141736 groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
Ben Noordhuis3ece1302012-12-04 05:36:231737 }
1738
Ben Noordhuis110a9cd2013-07-03 02:23:441739 args.GetReturnValue().Set(groups_list);
Ben Noordhuis3ece1302012-12-04 05:36:231740}
1741
1742
Ben Noordhuis110a9cd2013-07-03 02:23:441743static void SetGroups(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551744 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis3ece1302012-12-04 05:36:231745
1746 if (!args[0]->IsArray()) {
Fedor Indutny75adde02014-02-21 13:02:421747 return env->ThrowTypeError("argument 1 must be an array");
Ben Noordhuis3ece1302012-12-04 05:36:231748 }
1749
1750 Local<Array> groups_list = args[0].As<Array>();
1751 size_t size = groups_list->Length();
1752 gid_t* groups = new gid_t[size];
1753
1754 for (size_t i = 0; i < size; i++) {
1755 gid_t gid = gid_by_name(groups_list->Get(i));
1756
1757 if (gid == gid_not_found) {
1758 delete[] groups;
Fedor Indutny75adde02014-02-21 13:02:421759 return env->ThrowError("group name not found");
Ben Noordhuis3ece1302012-12-04 05:36:231760 }
1761
1762 groups[i] = gid;
1763 }
1764
1765 int rc = setgroups(size, groups);
1766 delete[] groups;
1767
1768 if (rc == -1) {
Fedor Indutny75adde02014-02-21 13:02:421769 return env->ThrowErrnoException(errno, "setgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231770 }
Ben Noordhuis3ece1302012-12-04 05:36:231771}
1772
1773
Ben Noordhuis110a9cd2013-07-03 02:23:441774static void InitGroups(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551775 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis3ece1302012-12-04 05:36:231776
1777 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421778 return env->ThrowTypeError("argument 1 must be a number or a string");
Ben Noordhuis3ece1302012-12-04 05:36:231779 }
1780
1781 if (!args[1]->IsUint32() && !args[1]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421782 return env->ThrowTypeError("argument 2 must be a number or a string");
Ben Noordhuis3ece1302012-12-04 05:36:231783 }
1784
Trevor Norriscbf76c12015-01-07 22:13:351785 node::Utf8Value arg0(env->isolate(), args[0]);
Ben Noordhuis3ece1302012-12-04 05:36:231786 gid_t extra_group;
1787 bool must_free;
1788 char* user;
1789
1790 if (args[0]->IsUint32()) {
1791 user = name_by_uid(args[0]->Uint32Value());
1792 must_free = true;
1793 } else {
1794 user = *arg0;
1795 must_free = false;
1796 }
1797
Ben Noordhuis2d82cdf2014-10-22 01:29:321798 if (user == nullptr) {
Fedor Indutny75adde02014-02-21 13:02:421799 return env->ThrowError("initgroups user not found");
Ben Noordhuis3ece1302012-12-04 05:36:231800 }
1801
1802 extra_group = gid_by_name(args[1]);
1803
1804 if (extra_group == gid_not_found) {
Fedor Indutny2bc30f22013-10-16 16:57:261805 if (must_free)
1806 free(user);
Fedor Indutny75adde02014-02-21 13:02:421807 return env->ThrowError("initgroups extra group not found");
Ben Noordhuis3ece1302012-12-04 05:36:231808 }
1809
1810 int rc = initgroups(user, extra_group);
1811
1812 if (must_free) {
1813 free(user);
1814 }
1815
1816 if (rc) {
Fedor Indutny75adde02014-02-21 13:02:421817 return env->ThrowErrnoException(errno, "initgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231818 }
Ben Noordhuis3ece1302012-12-04 05:36:231819}
1820
Fedor Indutny8e29ce92013-07-31 18:07:291821#endif // __POSIX__ && !defined(__ANDROID__)
Bert Belder30bab522010-11-25 00:09:061822
Michael Cartera3860762010-02-08 06:13:101823
Ben Noordhuis110a9cd2013-07-03 02:23:441824void Exit(const FunctionCallbackInfo<Value>& args) {
Rasmus Christian Pedersen734fb492014-09-18 12:10:531825 exit(args[0]->Int32Value());
Ryan0f517032009-04-29 09:09:321826}
1827
Ryan Dahl3ac6dee2010-05-08 02:05:591828
Ben Noordhuis110a9cd2013-07-03 02:23:441829static void Uptime(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551830 Environment* env = Environment::GetCurrent(args);
Igor Zinkovsky500c8f42011-12-15 20:36:051831 double uptime;
Tom Hughescf78ce52011-03-04 23:57:541832
Fedor Indutny6a610a02014-10-04 14:44:391833 uv_update_time(env->event_loop());
1834 uptime = uv_now(env->event_loop()) - prog_start_time;
Tom Hughescf78ce52011-03-04 23:57:541835
Timothy J Fontaineb19b60a2014-05-01 20:54:231836 args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
Tom Hughescf78ce52011-03-04 23:57:541837}
Ryan Dahl3ac6dee2010-05-08 02:05:591838
Ryan Dahlc344fbc2011-10-06 21:59:381839
Ben Noordhuis110a9cd2013-07-03 02:23:441840void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551841 Environment* env = Environment::GetCurrent(args);
Ryan Dahlb3b3cfe2009-11-03 12:00:421842
Ryan Dahl5783a522011-10-18 21:30:311843 size_t rss;
Ben Noordhuisca9eb712013-07-18 21:18:501844 int err = uv_resident_set_memory(&rss);
1845 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421846 return env->ThrowUVException(err, "uv_resident_set_memory");
Ryan Dahl3a701292009-11-03 00:30:011847 }
1848
Ryan Dahl38e425d2009-11-28 15:31:291849 // V8 memory usage
1850 HeapStatistics v8_heap_stats;
Fedor Indutny75adde02014-02-21 13:02:421851 env->isolate()->GetHeapStatistics(&v8_heap_stats);
Ben Noordhuis756b6222013-08-10 22:26:111852
1853 Local<Integer> heap_total =
Fedor Indutnyce04c722014-03-13 16:38:141854 Integer::NewFromUnsigned(env->isolate(), v8_heap_stats.total_heap_size());
Ben Noordhuis756b6222013-08-10 22:26:111855 Local<Integer> heap_used =
Fedor Indutnyce04c722014-03-13 16:38:141856 Integer::NewFromUnsigned(env->isolate(), v8_heap_stats.used_heap_size());
Ben Noordhuis756b6222013-08-10 22:26:111857
Fedor Indutnyce04c722014-03-13 16:38:141858 Local<Object> info = Object::New(env->isolate());
Fedor Indutny75adde02014-02-21 13:02:421859 info->Set(env->rss_string(), Number::New(env->isolate(), rss));
Ben Noordhuis756b6222013-08-10 22:26:111860 info->Set(env->heap_total_string(), heap_total);
1861 info->Set(env->heap_used_string(), heap_used);
Ryan Dahl38e425d2009-11-28 15:31:291862
Ben Noordhuis110a9cd2013-07-03 02:23:441863 args.GetReturnValue().Set(info);
Ryan Dahl3a701292009-11-03 00:30:011864}
Ryan Dahlb3b3cfe2009-11-03 12:00:421865
Bert Belder4a2cb072010-11-29 17:40:141866
Ben Noordhuis110a9cd2013-07-03 02:23:441867void Kill(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551868 Environment* env = Environment::GetCurrent(args);
Ryan Dahlb20c3432010-02-12 05:55:081869
Ryan Dahl4227e9d2010-12-21 23:40:101870 if (args.Length() != 2) {
Fedor Indutny75adde02014-02-21 13:02:421871 return env->ThrowError("Bad argument.");
Brandon Beacher334d56d2009-10-14 21:56:121872 }
Ryan Dahlb20c3432010-02-12 05:55:081873
Rasmus Christian Pedersen734fb492014-09-18 12:10:531874 int pid = args[0]->Int32Value();
Ryan Dahl6eca9482010-09-17 06:13:031875 int sig = args[1]->Int32Value();
Ben Noordhuisca9eb712013-07-18 21:18:501876 int err = uv_kill(pid, sig);
1877 args.GetReturnValue().Set(err);
Brandon Beacher334d56d2009-10-14 21:56:121878}
1879
Nathan Rajlich07c886f2012-03-05 16:51:581880// used in Hrtime() below
1881#define NANOS_PER_SEC 1000000000
1882
1883// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1884// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1885// so this function instead returns an Array with 2 entries representing seconds
1886// and nanoseconds, to avoid any integer overflow possibility.
1887// Pass in an Array from a previous hrtime() call to instead get a time diff.
Ben Noordhuis110a9cd2013-07-03 02:23:441888void Hrtime(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551889 Environment* env = Environment::GetCurrent(args);
Nathan Rajlich07c886f2012-03-05 16:51:581890
1891 uint64_t t = uv_hrtime();
1892
1893 if (args.Length() > 0) {
1894 // return a time diff tuple
Nathan Rajlichd3d83d72012-07-08 02:57:021895 if (!args[0]->IsArray()) {
Fedor Indutny75adde02014-02-21 13:02:421896 return env->ThrowTypeError(
1897 "process.hrtime() only accepts an Array tuple.");
Nathan Rajlichd3d83d72012-07-08 02:57:021898 }
Nathan Rajlich07c886f2012-03-05 16:51:581899 Local<Array> inArray = Local<Array>::Cast(args[0]);
1900 uint64_t seconds = inArray->Get(0)->Uint32Value();
1901 uint64_t nanos = inArray->Get(1)->Uint32Value();
1902 t -= (seconds * NANOS_PER_SEC) + nanos;
1903 }
1904
Fedor Indutnyce04c722014-03-13 16:38:141905 Local<Array> tuple = Array::New(env->isolate(), 2);
1906 tuple->Set(0, Integer::NewFromUnsigned(env->isolate(), t / NANOS_PER_SEC));
1907 tuple->Set(1, Integer::NewFromUnsigned(env->isolate(), t % NANOS_PER_SEC));
Ben Noordhuis110a9cd2013-07-03 02:23:441908 args.GetReturnValue().Set(tuple);
Nathan Rajlich07c886f2012-03-05 16:51:581909}
1910
Keith M Wesolowski76b98462013-12-17 00:00:441911extern "C" void node_module_register(void* m) {
1912 struct node_module* mp = reinterpret_cast<struct node_module*>(m);
1913
1914 if (mp->nm_flags & NM_F_BUILTIN) {
1915 mp->nm_link = modlist_builtin;
1916 modlist_builtin = mp;
Thorsten Lorenz0fe7a0d2014-09-15 17:00:221917 } else if (!node_is_initialized) {
1918 // "Linked" modules are included as part of the node project.
1919 // Like builtins they are registered *before* node::Init runs.
1920 mp->nm_flags = NM_F_LINKED;
1921 mp->nm_link = modlist_linked;
1922 modlist_linked = mp;
Keith M Wesolowski76b98462013-12-17 00:00:441923 } else {
Keith M Wesolowski76b98462013-12-17 00:00:441924 modpending = mp;
1925 }
1926}
1927
1928struct node_module* get_builtin_module(const char* name) {
1929 struct node_module* mp;
1930
Ben Noordhuis2d82cdf2014-10-22 01:29:321931 for (mp = modlist_builtin; mp != nullptr; mp = mp->nm_link) {
Keith M Wesolowski76b98462013-12-17 00:00:441932 if (strcmp(mp->nm_modname, name) == 0)
1933 break;
1934 }
1935
Ben Noordhuis2d82cdf2014-10-22 01:29:321936 CHECK(mp == nullptr || (mp->nm_flags & NM_F_BUILTIN) != 0);
Keith M Wesolowski76b98462013-12-17 00:00:441937 return (mp);
1938}
Bert Belderdd93c532011-10-28 10:05:091939
Thorsten Lorenz0fe7a0d2014-09-15 17:00:221940struct node_module* get_linked_module(const char* name) {
1941 struct node_module* mp;
1942
Bert Belder9483bfe2014-12-09 04:57:171943 for (mp = modlist_linked; mp != nullptr; mp = mp->nm_link) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:221944 if (strcmp(mp->nm_modname, name) == 0)
1945 break;
1946 }
1947
Bert Belder9483bfe2014-12-09 04:57:171948 CHECK(mp == nullptr || (mp->nm_flags & NM_F_LINKED) != 0);
Thorsten Lorenz0fe7a0d2014-09-15 17:00:221949 return mp;
1950}
1951
Bert Belderdd93c532011-10-28 10:05:091952typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
Ryan2b6d7242009-06-20 13:07:101953
isaacs15508582013-01-24 23:40:581954// DLOpen is process.dlopen(module, filename).
1955// Used to load 'module.node' dynamically shared objects.
Ben Noordhuis756b6222013-08-10 22:26:111956//
1957// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
1958// when two contexts try to load the same shared object. Maybe have a shadow
1959// cache that's a plain C list or hash table that's shared across contexts?
Ben Noordhuis110a9cd2013-07-03 02:23:441960void DLOpen(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551961 Environment* env = Environment::GetCurrent(args);
Bert Belderdd93c532011-10-28 10:05:091962 uv_lib_t lib;
Ryan2b6d7242009-06-20 13:07:101963
Ben Noordhuisa60056d2014-12-11 14:29:521964 CHECK_EQ(modpending, nullptr);
1965
toastynerd9419e1f2015-01-19 18:17:451966 if (args.Length() != 2) {
Fedor Indutny75adde02014-02-21 13:02:421967 env->ThrowError("process.dlopen takes exactly 2 arguments.");
Keith M Wesolowski76b98462013-12-17 00:00:441968 return;
Bert Belderdd93c532011-10-28 10:05:091969 }
Ryana97dce72009-08-31 09:14:341970
Trevor Norrisd5533862015-01-07 21:29:581971 Local<Object> module = args[0]->ToObject(env->isolate()); // Cast
Trevor Norriscbf76c12015-01-07 22:13:351972 node::Utf8Value filename(env->isolate(), args[1]); // Cast
Ben Noordhuisa60056d2014-12-11 14:29:521973 const bool is_dlopen_error = uv_dlopen(*filename, &lib);
isaacs15508582013-01-24 23:40:581974
Ben Noordhuisa60056d2014-12-11 14:29:521975 // Objects containing v14 or later modules will have registered themselves
1976 // on the pending list. Activate all of them now. At present, only one
1977 // module per object is supported.
1978 node_module* const mp = modpending;
1979 modpending = nullptr;
Ryan2b6d7242009-06-20 13:07:101980
Ben Noordhuisa60056d2014-12-11 14:29:521981 if (is_dlopen_error) {
Ben Noordhuis756b6222013-08-10 22:26:111982 Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
Ben Noordhuis039fac62012-05-17 05:13:291983#ifdef _WIN32
1984 // Windows needs to add the filename into the error message
Trevor Norrisd5533862015-01-07 21:29:581985 errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
Fedor Indutny8e29ce92013-07-31 18:07:291986#endif // _WIN32
Fedor Indutny75adde02014-02-21 13:02:421987 env->isolate()->ThrowException(Exception::Error(errmsg));
Ben Noordhuis110a9cd2013-07-03 02:23:441988 return;
Ryan2b6d7242009-06-20 13:07:101989 }
1990
Ben Noordhuis2d82cdf2014-10-22 01:29:321991 if (mp == nullptr) {
Fedor Indutny75adde02014-02-21 13:02:421992 env->ThrowError("Module did not self-register.");
Keith M Wesolowski76b98462013-12-17 00:00:441993 return;
Paul Querna367b87d2010-07-13 08:33:511994 }
Keith M Wesolowski76b98462013-12-17 00:00:441995 if (mp->nm_version != NODE_MODULE_VERSION) {
Ben Noordhuisf6923472012-07-26 23:06:121996 char errmsg[1024];
1997 snprintf(errmsg,
1998 sizeof(errmsg),
1999 "Module version mismatch. Expected %d, got %d.",
Keith M Wesolowski76b98462013-12-17 00:00:442000 NODE_MODULE_VERSION, mp->nm_version);
Fedor Indutny75adde02014-02-21 13:02:422001 env->ThrowError(errmsg);
Keith M Wesolowski76b98462013-12-17 00:00:442002 return;
2003 }
2004 if (mp->nm_flags & NM_F_BUILTIN) {
Fedor Indutny75adde02014-02-21 13:02:422005 env->ThrowError("Built-in module self-registered.");
Keith M Wesolowski76b98462013-12-17 00:00:442006 return;
Ryan2b6d7242009-06-20 13:07:102007 }
Ryan2b6d7242009-06-20 13:07:102008
Keith M Wesolowski76b98462013-12-17 00:00:442009 mp->nm_dso_handle = lib.handle;
2010 mp->nm_link = modlist_addon;
2011 modlist_addon = mp;
2012
Ben Noordhuisa60056d2014-12-11 14:29:522013 Local<String> exports_string = env->exports_string();
Trevor Norrisd5533862015-01-07 21:29:582014 Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());
Ben Noordhuisa60056d2014-12-11 14:29:522015
Ben Noordhuis2d82cdf2014-10-22 01:29:322016 if (mp->nm_context_register_func != nullptr) {
Keith M Wesolowski76b98462013-12-17 00:00:442017 mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
Ben Noordhuis2d82cdf2014-10-22 01:29:322018 } else if (mp->nm_register_func != nullptr) {
Keith M Wesolowski76b98462013-12-17 00:00:442019 mp->nm_register_func(exports, module, mp->nm_priv);
Ben Noordhuis756b6222013-08-10 22:26:112020 } else {
Fedor Indutny75adde02014-02-21 13:02:422021 env->ThrowError("Module has no declared entry point.");
Keith M Wesolowski76b98462013-12-17 00:00:442022 return;
Ben Noordhuis756b6222013-08-10 22:26:112023 }
Ryan2b6d7242009-06-20 13:07:102024
Peter Griess4e3c5d82010-07-12 15:47:452025 // Tell coverity that 'handle' should not be freed when we return.
2026 // coverity[leaked_storage]
Ryan2b6d7242009-06-20 13:07:102027}
2028
Tim-Smartae10a482010-03-12 08:36:002029
Ryand6c9d312009-09-11 14:02:292030static void OnFatalError(const char* location, const char* message) {
Ryan Dahl53a841d2009-12-29 19:20:512031 if (location) {
2032 fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
2033 } else {
2034 fprintf(stderr, "FATAL ERROR: %s\n", message);
2035 }
Ben Noordhuisc56a96c2013-06-29 05:30:112036 fflush(stderr);
Ben Noordhuisc56a96c2013-06-29 05:30:112037 abort();
Ryan63a9cd32009-04-15 08:08:282038}
2039
Miroslav Bajtosc16963b2013-06-17 19:19:592040
Trevor Norrisfa10b752013-06-20 23:44:022041NO_RETURN void FatalError(const char* location, const char* message) {
2042 OnFatalError(location, message);
2043 // to supress compiler warning
2044 abort();
2045}
2046
2047
Fedor Indutny75adde02014-02-21 13:02:422048void FatalException(Isolate* isolate,
2049 Handle<Value> error,
2050 Handle<Message> message) {
2051 HandleScope scope(isolate);
Felix Geisendörfer2b252ac2009-11-14 22:07:542052
Fedor Indutny75adde02014-02-21 13:02:422053 Environment* env = Environment::GetCurrent(isolate);
Ben Noordhuis756b6222013-08-10 22:26:112054 Local<Object> process_object = env->process_object();
2055 Local<String> fatal_exception_string = env->fatal_exception_string();
2056 Local<Function> fatal_exception_function =
2057 process_object->Get(fatal_exception_string).As<Function>();
Ryan Dahl45a806a2009-12-09 08:02:212058
Ben Noordhuis756b6222013-08-10 22:26:112059 if (!fatal_exception_function->IsFunction()) {
isaacs4401bb42012-12-26 20:28:332060 // failed before the process._fatalException function was added!
2061 // this is probably pretty bad. Nothing to do but report and exit.
Fedor Indutnyf1de13b2014-02-05 16:38:332062 ReportException(env, error, message);
isaacs95862b22013-02-27 19:23:202063 exit(6);
Felix Geisendörfer2b252ac2009-11-14 22:07:542064 }
2065
isaacs4401bb42012-12-26 20:28:332066 TryCatch fatal_try_catch;
isaacs07be9fc2012-05-09 22:12:132067
Miroslav Bajtosc16963b2013-06-17 19:19:592068 // Do not call FatalException when _fatalException handler throws
2069 fatal_try_catch.SetVerbose(false);
2070
isaacs4401bb42012-12-26 20:28:332071 // this will return true if the JS layer handled it, false otherwise
Ben Noordhuis756b6222013-08-10 22:26:112072 Local<Value> caught =
2073 fatal_exception_function->Call(process_object, 1, &error);
isaacs4401bb42012-12-26 20:28:332074
2075 if (fatal_try_catch.HasCaught()) {
2076 // the fatal exception function threw, so we must exit
Fedor Indutnyf1de13b2014-02-05 16:38:332077 ReportException(env, fatal_try_catch);
isaacs95862b22013-02-27 19:23:202078 exit(7);
isaacs4401bb42012-12-26 20:28:332079 }
2080
2081 if (false == caught->BooleanValue()) {
Fedor Indutnyf1de13b2014-02-05 16:38:332082 ReportException(env, error, message);
isaacsb30a03e2013-09-07 00:47:562083 exit(1);
isaacs80a55e92012-04-07 02:23:162084 }
Ryane78917b2009-03-09 13:08:312085}
2086
Ryan0e9e9272009-04-04 14:53:432087
Fedor Indutny75adde02014-02-21 13:02:422088void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2089 HandleScope scope(isolate);
Fedor Indutny8e29ce92013-07-31 18:07:292090 // TODO(bajtos) do not call FatalException if try_catch is verbose
Miroslav Bajtosc16963b2013-06-17 19:19:592091 // (requires V8 API to expose getter for try_catch.is_verbose_)
Fedor Indutny75adde02014-02-21 13:02:422092 FatalException(isolate, try_catch.Exception(), try_catch.Message());
Miroslav Bajtosc16963b2013-06-17 19:19:592093}
2094
2095
2096void OnMessage(Handle<Message> message, Handle<Value> error) {
2097 // The current version of V8 sends messages for errors only
2098 // (thus `error` is always set).
Fedor Indutny75adde02014-02-21 13:02:422099 FatalException(Isolate::GetCurrent(), error, message);
Miroslav Bajtosc16963b2013-06-17 19:19:592100}
2101
2102
Ben Noordhuis110a9cd2013-07-03 02:23:442103static void Binding(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:552104 Environment* env = Environment::GetCurrent(args);
Ryan Dahl627fb5a2010-03-15 20:48:032105
Trevor Norrisd5533862015-01-07 21:29:582106 Local<String> module = args[0]->ToString(env->isolate());
Trevor Norriscbf76c12015-01-07 22:13:352107 node::Utf8Value module_v(env->isolate(), module);
Ryan Dahl627fb5a2010-03-15 20:48:032108
Ben Noordhuis756b6222013-08-10 22:26:112109 Local<Object> cache = env->binding_cache_object();
Ryan Dahl627fb5a2010-03-15 20:48:032110 Local<Object> exports;
2111
Ben Noordhuis110a9cd2013-07-03 02:23:442112 if (cache->Has(module)) {
Trevor Norrisd5533862015-01-07 21:29:582113 exports = cache->Get(module)->ToObject(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442114 args.GetReturnValue().Set(exports);
2115 return;
Ryan Dahlea9ee1f2011-07-28 02:30:322116 }
Ryan Dahl6eca9482010-09-17 06:13:032117
Ryan Dahlea9ee1f2011-07-28 02:30:322118 // Append a string to process.moduleLoadList
2119 char buf[1024];
Fedor Indutny8e29ce92013-07-31 18:07:292120 snprintf(buf, sizeof(buf), "Binding %s", *module_v);
Ben Noordhuis110a9cd2013-07-03 02:23:442121
Ben Noordhuis756b6222013-08-10 22:26:112122 Local<Array> modules = env->module_load_list_array();
Ben Noordhuis110a9cd2013-07-03 02:23:442123 uint32_t l = modules->Length();
Fedor Indutny75adde02014-02-21 13:02:422124 modules->Set(l, OneByteString(env->isolate(), buf));
Ryan Dahlea9ee1f2011-07-28 02:30:322125
Keith M Wesolowski76b98462013-12-17 00:00:442126 node_module* mod = get_builtin_module(*module_v);
Ben Noordhuis2d82cdf2014-10-22 01:29:322127 if (mod != nullptr) {
Fedor Indutnyce04c722014-03-13 16:38:142128 exports = Object::New(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:112129 // Internal bindings don't have a "module" object, only exports.
Ben Noordhuis2d82cdf2014-10-22 01:29:322130 CHECK_EQ(mod->nm_register_func, nullptr);
2131 CHECK_NE(mod->nm_context_register_func, nullptr);
Ben Noordhuis756b6222013-08-10 22:26:112132 Local<Value> unused = Undefined(env->isolate());
Keith M Wesolowski76b98462013-12-17 00:00:442133 mod->nm_context_register_func(exports, unused,
2134 env->context(), mod->nm_priv);
Ben Noordhuis110a9cd2013-07-03 02:23:442135 cache->Set(module, exports);
Ryan Dahl6eca9482010-09-17 06:13:032136 } else if (!strcmp(*module_v, "constants")) {
Fedor Indutnyce04c722014-03-13 16:38:142137 exports = Object::New(env->isolate());
Ryan Dahl6eca9482010-09-17 06:13:032138 DefineConstants(exports);
Ben Noordhuis110a9cd2013-07-03 02:23:442139 cache->Set(module, exports);
Ryan Dahlc90546f2010-03-15 21:22:502140 } else if (!strcmp(*module_v, "natives")) {
Fedor Indutnyce04c722014-03-13 16:38:142141 exports = Object::New(env->isolate());
Fedor Indutny75adde02014-02-21 13:02:422142 DefineJavaScript(env, exports);
Ben Noordhuis110a9cd2013-07-03 02:23:442143 cache->Set(module, exports);
Ryan Dahl627fb5a2010-03-15 20:48:032144 } else {
Jackson Tian962e6512014-08-01 11:26:092145 char errmsg[1024];
2146 snprintf(errmsg,
2147 sizeof(errmsg),
2148 "No such module: %s",
2149 *module_v);
2150 return env->ThrowError(errmsg);
Ryan Dahl627fb5a2010-03-15 20:48:032151 }
2152
Ben Noordhuis110a9cd2013-07-03 02:23:442153 args.GetReturnValue().Set(exports);
Ryan Dahl627fb5a2010-03-15 20:48:032154}
2155
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222156static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
2157 Environment* env = Environment::GetCurrent(args.GetIsolate());
2158
Trevor Norrisd5533862015-01-07 21:29:582159 Local<String> module = args[0]->ToString(env->isolate());
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222160
2161 Local<Object> cache = env->binding_cache_object();
2162 Local<Value> exports_v = cache->Get(module);
2163
2164 if (exports_v->IsObject())
2165 return args.GetReturnValue().Set(exports_v.As<Object>());
2166
Trevor Norriscbf76c12015-01-07 22:13:352167 node::Utf8Value module_v(env->isolate(), module);
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222168 node_module* mod = get_linked_module(*module_v);
2169
Bert Belder9483bfe2014-12-09 04:57:172170 if (mod == nullptr) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222171 char errmsg[1024];
2172 snprintf(errmsg,
2173 sizeof(errmsg),
2174 "No such module was linked: %s",
2175 *module_v);
2176 return env->ThrowError(errmsg);
2177 }
2178
2179 Local<Object> exports = Object::New(env->isolate());
2180
Bert Belder9483bfe2014-12-09 04:57:172181 if (mod->nm_context_register_func != nullptr) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222182 mod->nm_context_register_func(exports,
2183 module,
2184 env->context(),
2185 mod->nm_priv);
Bert Belder9483bfe2014-12-09 04:57:172186 } else if (mod->nm_register_func != nullptr) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222187 mod->nm_register_func(exports, module, mod->nm_priv);
2188 } else {
2189 return env->ThrowError("Linked module has no declared entry point.");
2190 }
2191
2192 cache->Set(module, exports);
2193
2194 args.GetReturnValue().Set(exports);
2195}
Ryan Dahle742d072009-10-09 11:25:042196
Ben Noordhuis110a9cd2013-07-03 02:23:442197static void ProcessTitleGetter(Local<String> property,
2198 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422199 Environment* env = Environment::GetCurrent(info.GetIsolate());
2200 HandleScope scope(env->isolate());
Igor Zinkovsky500c8f42011-12-15 20:36:052201 char buffer[512];
2202 uv_get_process_title(buffer, sizeof(buffer));
Fedor Indutny75adde02014-02-21 13:02:422203 info.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), buffer));
Ryan Dahl5185c152010-06-18 07:26:492204}
2205
2206
2207static void ProcessTitleSetter(Local<String> property,
2208 Local<Value> value,
Ben Noordhuis110a9cd2013-07-03 02:23:442209 const PropertyCallbackInfo<void>& info) {
Fedor Indutny75adde02014-02-21 13:02:422210 Environment* env = Environment::GetCurrent(info.GetIsolate());
2211 HandleScope scope(env->isolate());
Trevor Norriscbf76c12015-01-07 22:13:352212 node::Utf8Value title(env->isolate(), value);
Fedor Indutny8e29ce92013-07-31 18:07:292213 // TODO(piscisaureus): protect with a lock
Igor Zinkovsky500c8f42011-12-15 20:36:052214 uv_set_process_title(*title);
Ryan Dahl5185c152010-06-18 07:26:492215}
2216
2217
Ben Noordhuis110a9cd2013-07-03 02:23:442218static void EnvGetter(Local<String> property,
2219 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422220 Environment* env = Environment::GetCurrent(info.GetIsolate());
2221 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182222#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352223 node::Utf8Value key(env->isolate(), property);
Ben Noordhuisb4def482010-10-15 13:48:342224 const char* val = getenv(*key);
2225 if (val) {
Fedor Indutny75adde02014-02-21 13:02:422226 return info.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), val));
Ben Noordhuisb4def482010-10-15 13:48:342227 }
Bert Belder077f9d72012-02-15 22:34:182228#else // _WIN32
2229 String::Value key(property);
Fedor Indutny8e29ce92013-07-31 18:07:292230 WCHAR buffer[32767]; // The maximum size allowed for environment variables.
Bert Belder077f9d72012-02-15 22:34:182231 DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2232 buffer,
2233 ARRAY_SIZE(buffer));
2234 // If result >= sizeof buffer the buffer was too small. That should never
2235 // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2236 // not found.
2237 if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2238 result < ARRAY_SIZE(buffer)) {
Ben Noordhuisf674b092013-08-07 19:50:412239 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
Fedor Indutny75adde02014-02-21 13:02:422240 Local<String> rc = String::NewFromTwoByte(env->isolate(), two_byte_buffer);
Ben Noordhuisf674b092013-08-07 19:50:412241 return info.GetReturnValue().Set(rc);
Bert Belder077f9d72012-02-15 22:34:182242 }
2243#endif
Ben Noordhuisfee02db2012-06-29 15:29:322244 // Not found. Fetch from prototype.
Ben Noordhuis110a9cd2013-07-03 02:23:442245 info.GetReturnValue().Set(
2246 info.Data().As<Object>()->Get(property));
Ben Noordhuisb4def482010-10-15 13:48:342247}
2248
2249
Ben Noordhuis110a9cd2013-07-03 02:23:442250static void EnvSetter(Local<String> property,
2251 Local<Value> value,
2252 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422253 Environment* env = Environment::GetCurrent(info.GetIsolate());
2254 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182255#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352256 node::Utf8Value key(env->isolate(), property);
2257 node::Utf8Value val(env->isolate(), value);
Ben Noordhuisb4def482010-10-15 13:48:342258 setenv(*key, *val, 1);
Bert Belder077f9d72012-02-15 22:34:182259#else // _WIN32
2260 String::Value key(property);
2261 String::Value val(value);
2262 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2263 // Environment variables that start with '=' are read-only.
2264 if (key_ptr[0] != L'=') {
2265 SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
Ryan Dahle6b06bc2011-08-11 00:14:232266 }
Bert Belder30bab522010-11-25 00:09:062267#endif
Bert Belder077f9d72012-02-15 22:34:182268 // Whether it worked or not, always return rval.
Ben Noordhuis110a9cd2013-07-03 02:23:442269 info.GetReturnValue().Set(value);
Ben Noordhuisb4def482010-10-15 13:48:342270}
2271
2272
Ben Noordhuis110a9cd2013-07-03 02:23:442273static void EnvQuery(Local<String> property,
2274 const PropertyCallbackInfo<Integer>& info) {
Fedor Indutny75adde02014-02-21 13:02:422275 Environment* env = Environment::GetCurrent(info.GetIsolate());
2276 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442277 int32_t rc = -1; // Not found unless proven otherwise.
Bert Belder077f9d72012-02-15 22:34:182278#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352279 node::Utf8Value key(env->isolate(), property);
Fedor Indutny2bc30f22013-10-16 16:57:262280 if (getenv(*key))
2281 rc = 0;
Bert Belder077f9d72012-02-15 22:34:182282#else // _WIN32
2283 String::Value key(property);
2284 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
Ben Noordhuis2d82cdf2014-10-22 01:29:322285 if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
Bert Belder077f9d72012-02-15 22:34:182286 GetLastError() == ERROR_SUCCESS) {
Ben Noordhuis110a9cd2013-07-03 02:23:442287 rc = 0;
Bert Belder077f9d72012-02-15 22:34:182288 if (key_ptr[0] == L'=') {
2289 // Environment variables that start with '=' are hidden and read-only.
Ben Noordhuis110a9cd2013-07-03 02:23:442290 rc = static_cast<int32_t>(v8::ReadOnly) |
2291 static_cast<int32_t>(v8::DontDelete) |
2292 static_cast<int32_t>(v8::DontEnum);
Bert Belder077f9d72012-02-15 22:34:182293 }
2294 }
2295#endif
Fedor Indutny2bc30f22013-10-16 16:57:262296 if (rc != -1)
2297 info.GetReturnValue().Set(rc);
Ben Noordhuisb4def482010-10-15 13:48:342298}
2299
2300
Ben Noordhuis110a9cd2013-07-03 02:23:442301static void EnvDeleter(Local<String> property,
2302 const PropertyCallbackInfo<Boolean>& info) {
Fedor Indutny75adde02014-02-21 13:02:422303 Environment* env = Environment::GetCurrent(info.GetIsolate());
2304 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442305 bool rc = true;
Bert Belder30bab522010-11-25 00:09:062306#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352307 node::Utf8Value key(env->isolate(), property);
Ben Noordhuis2d82cdf2014-10-22 01:29:322308 rc = getenv(*key) != nullptr;
Fedor Indutny2bc30f22013-10-16 16:57:262309 if (rc)
2310 unsetenv(*key);
Bert Belder30bab522010-11-25 00:09:062311#else
Bert Belder077f9d72012-02-15 22:34:182312 String::Value key(property);
2313 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
Ben Noordhuis2d82cdf2014-10-22 01:29:322314 if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, nullptr)) {
Bert Belder077f9d72012-02-15 22:34:182315 // Deletion failed. Return true if the key wasn't there in the first place,
2316 // false if it is still there.
Ben Noordhuis2d82cdf2014-10-22 01:29:322317 rc = GetEnvironmentVariableW(key_ptr, nullptr, 0) == 0 &&
Ben Noordhuis110a9cd2013-07-03 02:23:442318 GetLastError() != ERROR_SUCCESS;
Ben Noordhuisb4def482010-10-15 13:48:342319 }
Bert Belder077f9d72012-02-15 22:34:182320#endif
Ben Noordhuis110a9cd2013-07-03 02:23:442321 info.GetReturnValue().Set(rc);
Ben Noordhuisb4def482010-10-15 13:48:342322}
2323
2324
Ben Noordhuis110a9cd2013-07-03 02:23:442325static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
Fedor Indutny75adde02014-02-21 13:02:422326 Environment* env = Environment::GetCurrent(info.GetIsolate());
2327 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182328#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:342329 int size = 0;
Fedor Indutny2bc30f22013-10-16 16:57:262330 while (environ[size])
2331 size++;
Ben Noordhuisb4def482010-10-15 13:48:342332
Fedor Indutnyce04c722014-03-13 16:38:142333 Local<Array> envarr = Array::New(env->isolate(), size);
Ben Noordhuisb4def482010-10-15 13:48:342334
2335 for (int i = 0; i < size; ++i) {
2336 const char* var = environ[i];
2337 const char* s = strchr(var, '=');
2338 const int length = s ? s - var : strlen(var);
Fedor Indutny75adde02014-02-21 13:02:422339 Local<String> name = String::NewFromUtf8(env->isolate(),
Ben Noordhuisf674b092013-08-07 19:50:412340 var,
2341 String::kNormalString,
2342 length);
Fedor Indutny75adde02014-02-21 13:02:422343 envarr->Set(i, name);
Ben Noordhuisb4def482010-10-15 13:48:342344 }
Bert Belder077f9d72012-02-15 22:34:182345#else // _WIN32
2346 WCHAR* environment = GetEnvironmentStringsW();
Ben Noordhuis2d82cdf2014-10-22 01:29:322347 if (environment == nullptr)
Fedor Indutny2bc30f22013-10-16 16:57:262348 return; // This should not happen.
Fedor Indutnyce04c722014-03-13 16:38:142349 Local<Array> envarr = Array::New(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182350 WCHAR* p = environment;
2351 int i = 0;
Nikolai Vavilovb105f6f2014-10-24 22:36:592352 while (*p) {
Bert Belder077f9d72012-02-15 22:34:182353 WCHAR *s;
2354 if (*p == L'=') {
2355 // If the key starts with '=' it is a hidden environment variable.
2356 p += wcslen(p) + 1;
2357 continue;
2358 } else {
2359 s = wcschr(p, L'=');
2360 }
2361 if (!s) {
2362 s = p + wcslen(p);
2363 }
Ben Noordhuisf674b092013-08-07 19:50:412364 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
Ben Noordhuis78f709d2013-08-09 15:43:102365 const size_t two_byte_buffer_len = s - p;
Fedor Indutny75adde02014-02-21 13:02:422366 Local<String> value = String::NewFromTwoByte(env->isolate(),
Ben Noordhuis78f709d2013-08-09 15:43:102367 two_byte_buffer,
2368 String::kNormalString,
2369 two_byte_buffer_len);
Fedor Indutny75adde02014-02-21 13:02:422370 envarr->Set(i++, value);
Bert Belder077f9d72012-02-15 22:34:182371 p = s + wcslen(s) + 1;
2372 }
2373 FreeEnvironmentStringsW(environment);
2374#endif
Ben Noordhuis110a9cd2013-07-03 02:23:442375
Fedor Indutny75adde02014-02-21 13:02:422376 info.GetReturnValue().Set(envarr);
Ben Noordhuisb4def482010-10-15 13:48:342377}
2378
2379
Fedor Indutny75adde02014-02-21 13:02:422380static Handle<Object> GetFeatures(Environment* env) {
Fedor Indutnyce04c722014-03-13 16:38:142381 EscapableHandleScope scope(env->isolate());
Ben Noordhuisaa0308d2011-07-23 21:16:482382
Fedor Indutnyce04c722014-03-13 16:38:142383 Local<Object> obj = Object::New(env->isolate());
Ryan Dahl52a40e02011-08-24 21:16:352384#if defined(DEBUG) && DEBUG
Fedor Indutny75adde02014-02-21 13:02:422385 Local<Value> debug = True(env->isolate());
Ryan Dahl52a40e02011-08-24 21:16:352386#else
Fedor Indutny75adde02014-02-21 13:02:422387 Local<Value> debug = False(env->isolate());
Fedor Indutny8e29ce92013-07-31 18:07:292388#endif // defined(DEBUG) && DEBUG
2389
Fedor Indutny75adde02014-02-21 13:02:422390 obj->Set(env->debug_string(), debug);
Ryan Dahl52a40e02011-08-24 21:16:352391
Fedor Indutny75adde02014-02-21 13:02:422392 obj->Set(env->uv_string(), True(env->isolate()));
Fedor Indutny8e29ce92013-07-31 18:07:292393 // TODO(bnoordhuis) ping libuv
Fedor Indutny75adde02014-02-21 13:02:422394 obj->Set(env->ipv6_lc_string(), True(env->isolate()));
Ben Noordhuisf674b092013-08-07 19:50:412395
Ben Noordhuis8d567f42013-08-27 14:14:452396#ifdef OPENSSL_NPN_NEGOTIATED
Fedor Indutny75adde02014-02-21 13:02:422397 Local<Boolean> tls_npn = True(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452398#else
Fedor Indutny75adde02014-02-21 13:02:422399 Local<Boolean> tls_npn = False(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452400#endif
Fedor Indutny75adde02014-02-21 13:02:422401 obj->Set(env->tls_npn_string(), tls_npn);
Ben Noordhuis8d567f42013-08-27 14:14:452402
2403#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
Fedor Indutny75adde02014-02-21 13:02:422404 Local<Boolean> tls_sni = True(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452405#else
Fedor Indutny75adde02014-02-21 13:02:422406 Local<Boolean> tls_sni = False(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452407#endif
Fedor Indutny75adde02014-02-21 13:02:422408 obj->Set(env->tls_sni_string(), tls_sni);
Ben Noordhuis8d567f42013-08-27 14:14:452409
Fedor Indutnyb3ef2892014-04-14 17:15:572410#if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2411 Local<Boolean> tls_ocsp = True(env->isolate());
2412#else
2413 Local<Boolean> tls_ocsp = False(env->isolate());
2414#endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2415 obj->Set(env->tls_ocsp_string(), tls_ocsp);
2416
Fedor Indutny75adde02014-02-21 13:02:422417 obj->Set(env->tls_string(),
Ben Noordhuis2d82cdf2014-10-22 01:29:322418 Boolean::New(env->isolate(),
2419 get_builtin_module("crypto") != nullptr));
Ben Noordhuisaa0308d2011-07-23 21:16:482420
Fedor Indutnyce04c722014-03-13 16:38:142421 return scope.Escape(obj);
Ben Noordhuisaa0308d2011-07-23 21:16:482422}
2423
2424
Ben Noordhuis110a9cd2013-07-03 02:23:442425static void DebugPortGetter(Local<String> property,
2426 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422427 Environment* env = Environment::GetCurrent(info.GetIsolate());
2428 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442429 info.GetReturnValue().Set(debug_port);
Fedor Indutny3f43b1c2012-02-12 15:53:432430}
2431
2432
2433static void DebugPortSetter(Local<String> property,
2434 Local<Value> value,
Ben Noordhuis110a9cd2013-07-03 02:23:442435 const PropertyCallbackInfo<void>& info) {
Fedor Indutny75adde02014-02-21 13:02:422436 Environment* env = Environment::GetCurrent(info.GetIsolate());
2437 HandleScope scope(env->isolate());
Rasmus Christian Pedersen734fb492014-09-18 12:10:532438 debug_port = value->Int32Value();
Fedor Indutny3f43b1c2012-02-12 15:53:432439}
2440
2441
Ben Noordhuis110a9cd2013-07-03 02:23:442442static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2443static void DebugPause(const FunctionCallbackInfo<Value>& args);
2444static void DebugEnd(const FunctionCallbackInfo<Value>& args);
Bert Belder829735e2011-11-04 15:23:022445
Shigeki Ohtsucd372512013-02-06 02:13:022446
Ben Noordhuis110a9cd2013-07-03 02:23:442447void NeedImmediateCallbackGetter(Local<String> property,
2448 const PropertyCallbackInfo<Value>& info) {
Ben Noordhuis756b6222013-08-10 22:26:112449 Environment* env = Environment::GetCurrent(info.GetIsolate());
2450 const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2451 bool active = uv_is_active(
2452 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2453 info.GetReturnValue().Set(active);
Shigeki Ohtsucd372512013-02-06 02:13:022454}
2455
2456
Ben Noordhuis756b6222013-08-10 22:26:112457static void NeedImmediateCallbackSetter(
2458 Local<String> property,
2459 Local<Value> value,
2460 const PropertyCallbackInfo<void>& info) {
Ben Noordhuis756b6222013-08-10 22:26:112461 HandleScope handle_scope(info.GetIsolate());
Ben Noordhuis09724b32013-11-11 21:02:032462 Environment* env = Environment::GetCurrent(info.GetIsolate());
Shigeki Ohtsucd372512013-02-06 02:13:022463
Ben Noordhuis756b6222013-08-10 22:26:112464 uv_check_t* immediate_check_handle = env->immediate_check_handle();
2465 bool active = uv_is_active(
2466 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
Shigeki Ohtsucd372512013-02-06 02:13:022467
Ben Noordhuis756b6222013-08-10 22:26:112468 if (active == value->BooleanValue())
2469 return;
Shigeki Ohtsucd372512013-02-06 02:13:022470
Ben Noordhuis756b6222013-08-10 22:26:112471 uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
Shigeki Ohtsucd372512013-02-06 02:13:022472
Ben Noordhuis756b6222013-08-10 22:26:112473 if (active) {
2474 uv_check_stop(immediate_check_handle);
2475 uv_idle_stop(immediate_idle_handle);
Shigeki Ohtsucd372512013-02-06 02:13:022476 } else {
Ben Noordhuis756b6222013-08-10 22:26:112477 uv_check_start(immediate_check_handle, CheckImmediate);
2478 // Idle handle is needed only to stop the event loop from blocking in poll.
2479 uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
Shigeki Ohtsucd372512013-02-06 02:13:022480 }
2481}
2482
2483
Saúl Ibarra Corretgé42b93432014-03-12 23:08:292484void SetIdle(uv_prepare_t* handle) {
Ben Noordhuisf6496262013-10-03 09:03:462485 Environment* env = Environment::from_idle_prepare_handle(handle);
2486 env->isolate()->GetCpuProfiler()->SetIdle(true);
2487}
2488
2489
Saúl Ibarra Corretgé42b93432014-03-12 23:08:292490void ClearIdle(uv_check_t* handle) {
Ben Noordhuisf6496262013-10-03 09:03:462491 Environment* env = Environment::from_idle_check_handle(handle);
2492 env->isolate()->GetCpuProfiler()->SetIdle(false);
2493}
2494
2495
2496void StartProfilerIdleNotifier(Environment* env) {
2497 uv_prepare_start(env->idle_prepare_handle(), SetIdle);
2498 uv_check_start(env->idle_check_handle(), ClearIdle);
2499}
2500
2501
2502void StopProfilerIdleNotifier(Environment* env) {
2503 uv_prepare_stop(env->idle_prepare_handle());
2504 uv_check_stop(env->idle_check_handle());
2505}
2506
2507
2508void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:552509 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis09724b32013-11-11 21:02:032510 StartProfilerIdleNotifier(env);
Ben Noordhuisf6496262013-10-03 09:03:462511}
2512
2513
2514void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:552515 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis09724b32013-11-11 21:02:032516 StopProfilerIdleNotifier(env);
Ben Noordhuisf6496262013-10-03 09:03:462517}
2518
2519
Trevor Norrisc80f8fa2013-08-01 21:53:522520#define READONLY_PROPERTY(obj, str, var) \
2521 do { \
Fedor Indutny383b0c02014-10-08 10:34:512522 obj->ForceSet(OneByteString(env->isolate(), str), var, v8::ReadOnly); \
Trevor Norrisc80f8fa2013-08-01 21:53:522523 } while (0)
2524
2525
Ben Noordhuis756b6222013-08-10 22:26:112526void SetupProcessObject(Environment* env,
2527 int argc,
2528 const char* const* argv,
2529 int exec_argc,
2530 const char* const* exec_argv) {
Fedor Indutny75adde02014-02-21 13:02:422531 HandleScope scope(env->isolate());
Ryan Dahlcd1ec272011-01-02 09:44:422532
Ben Noordhuis756b6222013-08-10 22:26:112533 Local<Object> process = env->process_object();
Ben Noordhuis74a82152012-02-03 15:32:002534
Fedor Indutny75adde02014-02-21 13:02:422535 process->SetAccessor(env->title_string(),
Ryan Dahl5185c152010-06-18 07:26:492536 ProcessTitleGetter,
2537 ProcessTitleSetter);
2538
Ryan Dahlf4811832009-11-02 23:21:002539 // process.version
Ben Noordhuisf674b092013-08-07 19:50:412540 READONLY_PROPERTY(process,
2541 "version",
Fedor Indutny75adde02014-02-21 13:02:422542 FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
Ryan Dahl39b432e2010-08-17 18:24:102543
Ryan Dahlea9ee1f2011-07-28 02:30:322544 // process.moduleLoadList
Ben Noordhuis756b6222013-08-10 22:26:112545 READONLY_PROPERTY(process,
2546 "moduleLoadList",
2547 env->module_load_list_array());
Ryan Dahlea9ee1f2011-07-28 02:30:322548
Nathan Rajlich35043ad2012-03-13 23:04:172549 // process.versions
Fedor Indutnyce04c722014-03-13 16:38:142550 Local<Object> versions = Object::New(env->isolate());
Trevor Norrisc80f8fa2013-08-01 21:53:522551 READONLY_PROPERTY(process, "versions", versions);
Ben Noordhuisf674b092013-08-07 19:50:412552
2553 const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2554 "."
2555 NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR);
2556 READONLY_PROPERTY(versions,
2557 "http_parser",
Fedor Indutny75adde02014-02-21 13:02:422558 FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
Ben Noordhuisf674b092013-08-07 19:50:412559
Ryan Dahl39b432e2010-08-17 18:24:102560 // +1 to get rid of the leading 'v'
Ben Noordhuisf674b092013-08-07 19:50:412561 READONLY_PROPERTY(versions,
2562 "node",
Fedor Indutny75adde02014-02-21 13:02:422563 OneByteString(env->isolate(), NODE_VERSION + 1));
Ben Noordhuisf674b092013-08-07 19:50:412564 READONLY_PROPERTY(versions,
2565 "v8",
Fedor Indutny75adde02014-02-21 13:02:422566 OneByteString(env->isolate(), V8::GetVersion()));
Ben Noordhuisf674b092013-08-07 19:50:412567 READONLY_PROPERTY(versions,
2568 "uv",
Fedor Indutny75adde02014-02-21 13:02:422569 OneByteString(env->isolate(), uv_version_string()));
Ben Noordhuisf674b092013-08-07 19:50:412570 READONLY_PROPERTY(versions,
2571 "zlib",
Fedor Indutny75adde02014-02-21 13:02:422572 FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
Johan Bergström01736dd2015-01-14 00:12:052573 READONLY_PROPERTY(versions,
2574 "ares",
2575 FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
Ben Noordhuisf674b092013-08-07 19:50:412576
2577 const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
Fedor Indutny75adde02014-02-21 13:02:422578 READONLY_PROPERTY(
2579 versions,
2580 "modules",
2581 FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
Ben Noordhuisf674b092013-08-07 19:50:412582
Peter Bright13d6a1f2011-08-06 04:23:252583#if HAVE_OPENSSL
Ryan Dahlcd1ec272011-01-02 09:44:422584 // Stupid code to slice out the version string.
Ben Noordhuis7acdabb2013-11-04 21:42:482585 { // NOLINT(whitespace/braces)
Ben Noordhuis962686b2013-11-03 20:00:372586 size_t i, j, k;
2587 int c;
2588 for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
2589 c = OPENSSL_VERSION_TEXT[i];
2590 if ('0' <= c && c <= '9') {
2591 for (j = i + 1; j < k; ++j) {
2592 c = OPENSSL_VERSION_TEXT[j];
2593 if (c == ' ')
2594 break;
2595 }
2596 break;
Ryan Dahlcd1ec272011-01-02 09:44:422597 }
Ryan Dahlcd1ec272011-01-02 09:44:422598 }
Ben Noordhuis962686b2013-11-03 20:00:372599 READONLY_PROPERTY(
2600 versions,
2601 "openssl",
Fedor Indutny75adde02014-02-21 13:02:422602 OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
Ryan Dahlcd1ec272011-01-02 09:44:422603 }
Ryan Dahlcd1ec272011-01-02 09:44:422604#endif
Ryan Dahl39b432e2010-08-17 18:24:102605
Nathan Rajlichb1be5402011-04-26 03:24:512606 // process.arch
Bert Beldere1fe2702015-01-08 12:05:512607 READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH));
Nathan Rajlichb1be5402011-04-26 03:24:512608
Ryan Dahlf4811832009-11-02 23:21:002609 // process.platform
Vladimir Kurchatkin9f457992015-01-09 12:38:092610 READONLY_PROPERTY(process,
2611 "platform",
2612 OneByteString(env->isolate(), NODE_PLATFORM));
Ryan Dahlf4811832009-11-02 23:21:002613
Ryan Dahlf3ad6352010-02-03 20:19:082614 // process.argv
Fedor Indutnyce04c722014-03-13 16:38:142615 Local<Array> arguments = Array::New(env->isolate(), argc);
Ben Noordhuis185c5152013-09-02 14:42:012616 for (int i = 0; i < argc; ++i) {
Fedor Indutny75adde02014-02-21 13:02:422617 arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
Ryan27b268b2009-06-17 13:05:442618 }
Fedor Indutny75adde02014-02-21 13:02:422619 process->Set(env->argv_string(), arguments);
Ryan27b268b2009-06-17 13:05:442620
Micheil Smith19fd5302012-03-05 17:53:152621 // process.execArgv
Fedor Indutnyce04c722014-03-13 16:38:142622 Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
Ben Noordhuis185c5152013-09-02 14:42:012623 for (int i = 0; i < exec_argc; ++i) {
Fedor Indutny75adde02014-02-21 13:02:422624 exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
Micheil Smith19fd5302012-03-05 17:53:152625 }
Fedor Indutny75adde02014-02-21 13:02:422626 process->Set(env->exec_argv_string(), exec_arguments);
Micheil Smith19fd5302012-03-05 17:53:152627
Ryan Dahlf3ad6352010-02-03 20:19:082628 // create process.env
Fedor Indutnyce04c722014-03-13 16:38:142629 Local<ObjectTemplate> process_env_template =
2630 ObjectTemplate::New(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:112631 process_env_template->SetNamedPropertyHandler(EnvGetter,
2632 EnvSetter,
2633 EnvQuery,
2634 EnvDeleter,
2635 EnvEnumerator,
Fedor Indutnyce04c722014-03-13 16:38:142636 Object::New(env->isolate()));
Ben Noordhuis756b6222013-08-10 22:26:112637 Local<Object> process_env = process_env_template->NewInstance();
Fedor Indutny75adde02014-02-21 13:02:422638 process->Set(env->env_string(), process_env);
Ryan Dahlf3ad6352010-02-03 20:19:082639
Fedor Indutnyce04c722014-03-13 16:38:142640 READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
Fedor Indutny75adde02014-02-21 13:02:422641 READONLY_PROPERTY(process, "features", GetFeatures(env));
2642 process->SetAccessor(env->need_imm_cb_string(),
Ben Noordhuisf674b092013-08-07 19:50:412643 NeedImmediateCallbackGetter,
2644 NeedImmediateCallbackSetter);
Ryandc39e822009-09-10 12:07:352645
TJ Holowaychuk9481bc12010-10-07 02:05:012646 // -e, --eval
2647 if (eval_string) {
Ben Noordhuisf674b092013-08-07 19:50:412648 READONLY_PROPERTY(process,
2649 "_eval",
Fedor Indutny75adde02014-02-21 13:02:422650 String::NewFromUtf8(env->isolate(), eval_string));
Nathan Rajlichef3a8742012-04-24 08:24:132651 }
2652
2653 // -p, --print
2654 if (print_eval) {
Fedor Indutny75adde02014-02-21 13:02:422655 READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
TJ Holowaychuk9481bc12010-10-07 02:05:012656 }
2657
Nathan Rajlich6292df62012-04-24 08:32:332658 // -i, --interactive
Nathan Rajlichfeaa8a42012-03-21 07:05:252659 if (force_repl) {
Fedor Indutny75adde02014-02-21 13:02:422660 READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
Nathan Rajlichfeaa8a42012-03-21 07:05:252661 }
2662
isaacs5b399292012-06-21 18:42:332663 // --no-deprecation
2664 if (no_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422665 READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
isaacs5b399292012-06-21 18:42:332666 }
2667
isaacs5038f402013-03-06 01:46:372668 // --throw-deprecation
2669 if (throw_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422670 READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
isaacs5038f402013-03-06 01:46:372671 }
2672
isaacs5b399292012-06-21 18:42:332673 // --trace-deprecation
2674 if (trace_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422675 READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
isaacs5b399292012-06-21 18:42:332676 }
2677
Ben Noordhuisf674b092013-08-07 19:50:412678 size_t exec_path_len = 2 * PATH_MAX;
2679 char* exec_path = new char[exec_path_len];
2680 Local<String> exec_path_value;
2681 if (uv_exepath(exec_path, &exec_path_len) == 0) {
Fedor Indutny75adde02014-02-21 13:02:422682 exec_path_value = String::NewFromUtf8(env->isolate(),
Ben Noordhuisf674b092013-08-07 19:50:412683 exec_path,
2684 String::kNormalString,
2685 exec_path_len);
Marshall Culpepperca35ba62010-06-22 06:31:192686 } else {
Fedor Indutny75adde02014-02-21 13:02:422687 exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
Marshall Culpepperca35ba62010-06-22 06:31:192688 }
Fedor Indutny75adde02014-02-21 13:02:422689 process->Set(env->exec_path_string(), exec_path_value);
Ben Noordhuisf674b092013-08-07 19:50:412690 delete[] exec_path;
Marshall Culpepperca35ba62010-06-22 06:31:192691
Fedor Indutny75adde02014-02-21 13:02:422692 process->SetAccessor(env->debug_port_string(),
Fedor Indutny3f43b1c2012-02-12 15:53:432693 DebugPortGetter,
2694 DebugPortSetter);
2695
Ryan Dahl38814552009-10-09 15:15:472696 // define various internal methods
Ben Noordhuisd3c317e2014-10-13 13:19:552697 env->SetMethod(process,
2698 "_startProfilerIdleNotifier",
2699 StartProfilerIdleNotifier);
2700 env->SetMethod(process,
2701 "_stopProfilerIdleNotifier",
2702 StopProfilerIdleNotifier);
2703 env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
2704 env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
2705 env->SetMethod(process, "reallyExit", Exit);
2706 env->SetMethod(process, "abort", Abort);
2707 env->SetMethod(process, "chdir", Chdir);
2708 env->SetMethod(process, "cwd", Cwd);
Bert Belder30bab522010-11-25 00:09:062709
Ben Noordhuisd3c317e2014-10-13 13:19:552710 env->SetMethod(process, "umask", Umask);
Ryan Dahlacc120a2011-08-09 20:53:562711
Linus Mårtensson5e4e8ec2013-05-08 12:10:072712#if defined(__POSIX__) && !defined(__ANDROID__)
Ben Noordhuisd3c317e2014-10-13 13:19:552713 env->SetMethod(process, "getuid", GetUid);
2714 env->SetMethod(process, "setuid", SetUid);
James Duncandf1c1e52010-02-23 22:45:022715
Ben Noordhuisd3c317e2014-10-13 13:19:552716 env->SetMethod(process, "setgid", SetGid);
2717 env->SetMethod(process, "getgid", GetGid);
Ben Noordhuis3ece1302012-12-04 05:36:232718
Ben Noordhuisd3c317e2014-10-13 13:19:552719 env->SetMethod(process, "getgroups", GetGroups);
2720 env->SetMethod(process, "setgroups", SetGroups);
2721 env->SetMethod(process, "initgroups", InitGroups);
Fedor Indutny8e29ce92013-07-31 18:07:292722#endif // __POSIX__ && !defined(__ANDROID__)
James Duncandf1c1e52010-02-23 22:45:022723
Ben Noordhuisd3c317e2014-10-13 13:19:552724 env->SetMethod(process, "_kill", Kill);
Bert Belder30bab522010-11-25 00:09:062725
Ben Noordhuisd3c317e2014-10-13 13:19:552726 env->SetMethod(process, "_debugProcess", DebugProcess);
2727 env->SetMethod(process, "_debugPause", DebugPause);
2728 env->SetMethod(process, "_debugEnd", DebugEnd);
Bert Belder829735e2011-11-04 15:23:022729
Ben Noordhuisd3c317e2014-10-13 13:19:552730 env->SetMethod(process, "hrtime", Hrtime);
Nathan Rajlich07c886f2012-03-05 16:51:582731
Ben Noordhuisd3c317e2014-10-13 13:19:552732 env->SetMethod(process, "dlopen", DLOpen);
Bert Belderdd93c532011-10-28 10:05:092733
Ben Noordhuisd3c317e2014-10-13 13:19:552734 env->SetMethod(process, "uptime", Uptime);
2735 env->SetMethod(process, "memoryUsage", MemoryUsage);
Ryan27b268b2009-06-17 13:05:442736
Ben Noordhuisd3c317e2014-10-13 13:19:552737 env->SetMethod(process, "binding", Binding);
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222738 env->SetMethod(process, "_linkedBinding", LinkedBinding);
Ryan Dahl627fb5a2010-03-15 20:48:032739
Ben Noordhuisd3c317e2014-10-13 13:19:552740 env->SetMethod(process, "_setupNextTick", SetupNextTick);
2741 env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
Trevor Norrisf0b68892013-03-26 05:32:412742
Trevor Norris4f7f8bb2013-02-26 17:47:362743 // pre-set _events object for faster emit checks
Fedor Indutnyce04c722014-03-13 16:38:142744 process->Set(env->events_string(), Object::New(env->isolate()));
Dean McNameef67e8f22011-03-15 22:39:162745}
2746
2747
Trevor Norrisc80f8fa2013-08-01 21:53:522748#undef READONLY_PROPERTY
2749
2750
Dean McNameef67e8f22011-03-15 22:39:162751static void AtExit() {
Ryan Dahl4e43afd2011-09-30 20:11:472752 uv_tty_reset_mode();
Dean McNameef67e8f22011-03-15 22:39:162753}
2754
2755
Geir Haugec61b0e92014-03-31 07:52:032756static void SignalExit(int signo) {
Ryan Dahl4e43afd2011-09-30 20:11:472757 uv_tty_reset_mode();
Geir Haugec61b0e92014-03-31 07:52:032758 raise(signo);
Dean McNameef67e8f22011-03-15 22:39:162759}
2760
2761
isaacs906a1752013-08-21 22:36:502762// Most of the time, it's best to use `console.error` to write
2763// to the process.stderr stream. However, in some cases, such as
2764// when debugging the stream.Writable class or the process.nextTick
2765// function, it is useful to bypass JavaScript entirely.
2766static void RawDebug(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis5fdff382014-10-11 14:52:072767 CHECK(args.Length() == 1 && args[0]->IsString() &&
2768 "must be called with a single string");
Trevor Norriscbf76c12015-01-07 22:13:352769 node::Utf8Value message(args.GetIsolate(), args[0]);
isaacs906a1752013-08-21 22:36:502770 fprintf(stderr, "%s\n", *message);
2771 fflush(stderr);
2772}
2773
2774
Fedor Indutny6a610a02014-10-04 14:44:392775void LoadEnvironment(Environment* env) {
Fedor Indutny75adde02014-02-21 13:02:422776 HandleScope handle_scope(env->isolate());
Ben Noordhuis34b0a362013-07-29 03:07:072777
Trevor Norrisd5533862015-01-07 21:29:582778 env->isolate()->SetFatalErrorHandler(node::OnFatalError);
2779 env->isolate()->AddMessageListener(OnMessage);
Fedor Indutny6a610a02014-10-04 14:44:392780
Ryan Dahl9f5643f2010-01-31 07:22:342781 // Compile, execute the src/node.js file. (Which was included as static C
2782 // string in node_natives.h. 'natve_node' is the string containing that
2783 // source code.)
Ryan Dahlb20c3432010-02-12 05:55:082784
Ryan Dahl9f5643f2010-01-31 07:22:342785 // The node.js file returns a function 'f'
Dean McNameef67e8f22011-03-15 22:39:162786 atexit(AtExit);
2787
Ryan Dahl9f5643f2010-01-31 07:22:342788 TryCatch try_catch;
Ryan Dahl9f5643f2010-01-31 07:22:342789
Miroslav Bajtosc16963b2013-06-17 19:19:592790 // Disable verbose mode to stop FatalException() handler from trying
2791 // to handle the exception. Errors this early in the start-up phase
2792 // are not safe to ignore.
2793 try_catch.SetVerbose(false);
2794
Fedor Indutnyf1de13b2014-02-05 16:38:332795 Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js");
Fedor Indutny75adde02014-02-21 13:02:422796 Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
Ryan Dahl9f5643f2010-01-31 07:22:342797 if (try_catch.HasCaught()) {
Fedor Indutnyf1de13b2014-02-05 16:38:332798 ReportException(env, try_catch);
Ryan Dahl9f5643f2010-01-31 07:22:342799 exit(10);
2800 }
Ben Noordhuis5fdff382014-10-11 14:52:072801 CHECK(f_value->IsFunction());
Ryan Dahl9f5643f2010-01-31 07:22:342802 Local<Function> f = Local<Function>::Cast(f_value);
2803
2804 // Now we call 'f' with the 'process' variable that we've built up with
2805 // all our bindings. Inside node.js we'll take care of assigning things to
2806 // their places.
Ryan Dahlb20c3432010-02-12 05:55:082807
Ryan Dahl9f5643f2010-01-31 07:22:342808 // We start the process this way in order to be more modular. Developers
2809 // who do not like how 'src/node.js' setups the module system but do like
2810 // Node's I/O bindings may want to replace 'f' with their own function.
2811
Ryan Dahlf8ce8482010-09-17 07:01:072812 // Add a reference to the global object
Ben Noordhuis756b6222013-08-10 22:26:112813 Local<Object> global = env->context()->Global();
Zoran Tomicicd98ea702010-02-22 05:15:442814
Ben Noordhuisc4def502013-10-28 19:18:592815#if defined HAVE_DTRACE || defined HAVE_ETW
Fedor Indutny75adde02014-02-21 13:02:422816 InitDTrace(env, global);
Ryan Dahle9257b82011-02-10 02:50:262817#endif
Ryan Dahl068b7332011-01-25 01:50:102818
Scott Blomquistf657ce62012-11-20 23:27:222819#if defined HAVE_PERFCTR
Fedor Indutny75adde02014-02-21 13:02:422820 InitPerfCounters(env, global);
Scott Blomquistf657ce62012-11-20 23:27:222821#endif
2822
Miroslav Bajtosc16963b2013-06-17 19:19:592823 // Enable handling of uncaught exceptions
2824 // (FatalException(), break on uncaught exception in debugger)
2825 //
2826 // This is not strictly necessary since it's almost impossible
2827 // to attach the debugger fast enought to break on exception
2828 // thrown during process startup.
2829 try_catch.SetVerbose(true);
Ryan Dahl9f5643f2010-01-31 07:22:342830
Ben Noordhuisd3c317e2014-10-13 13:19:552831 env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
isaacs906a1752013-08-21 22:36:502832
Ben Noordhuis756b6222013-08-10 22:26:112833 Local<Value> arg = env->process_object();
Ben Noordhuis110a9cd2013-07-03 02:23:442834 f->Call(global, 1, &arg);
Ryan27b268b2009-06-17 13:05:442835}
2836
Zoran Tomicicd98ea702010-02-22 05:15:442837static void PrintHelp();
2838
Ben Noordhuisbd9c6662013-11-16 13:39:412839static bool ParseDebugOpt(const char* arg) {
Ben Noordhuis2d82cdf2014-10-22 01:29:322840 const char* port = nullptr;
Zoran Tomicicd98ea702010-02-22 05:15:442841
Ben Noordhuisbd9c6662013-11-16 13:39:412842 if (!strcmp(arg, "--debug")) {
Miroslav Bajtoš43ec1b12013-05-02 06:34:222843 use_debug_agent = true;
Ben Noordhuisbd9c6662013-11-16 13:39:412844 } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
2845 use_debug_agent = true;
2846 port = arg + sizeof("--debug=") - 1;
2847 } else if (!strcmp(arg, "--debug-brk")) {
2848 use_debug_agent = true;
2849 debug_wait_connect = true;
2850 } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
2851 use_debug_agent = true;
2852 debug_wait_connect = true;
2853 port = arg + sizeof("--debug-brk=") - 1;
2854 } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
2855 port = arg + sizeof("--debug-port=") - 1;
2856 } else {
2857 return false;
2858 }
2859
Ben Noordhuis2d82cdf2014-10-22 01:29:322860 if (port != nullptr) {
Ben Noordhuisbd9c6662013-11-16 13:39:412861 debug_port = atoi(port);
2862 if (debug_port < 1024 || debug_port > 65535) {
2863 fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
2864 PrintHelp();
2865 exit(12);
Miroslav Bajtoš43ec1b12013-05-02 06:34:222866 }
Zoran Tomicicd98ea702010-02-22 05:15:442867 }
Zoran Tomicicd98ea702010-02-22 05:15:442868
Ben Noordhuisbd9c6662013-11-16 13:39:412869 return true;
Zoran Tomicicd98ea702010-02-22 05:15:442870}
2871
Ryand6c9d312009-09-11 14:02:292872static void PrintHelp() {
Jongyeol Choidaf95622015-01-16 14:45:372873 printf("Usage: iojs [options] [ -e script | script.js ] [arguments] \n"
2874 " iojs debug script.js [arguments] \n"
Ryan Dahl4fa712c2011-01-13 23:28:162875 "\n"
Ryan Dahl209b2192010-03-08 16:33:102876 "Options:\n"
Ben Noordhuis7d462472015-01-21 12:10:582877 " -v, --version print io.js version\n"
Steve Engledow292345f2011-07-05 11:07:082878 " -e, --eval script evaluate script\n"
Ben Noordhuiscb6d0842012-10-20 13:03:482879 " -p, --print evaluate script and print result\n"
Nathan Rajlichfeaa8a42012-03-21 07:05:252880 " -i, --interactive always enter the REPL even if stdin\n"
2881 " does not appear to be a terminal\n"
isaacs5b399292012-06-21 18:42:332882 " --no-deprecation silence deprecation warnings\n"
Trevor Norrisf10fd1d2014-05-07 21:47:572883 " --throw-deprecation throw an exception anytime a deprecated "
2884 "function is used\n"
isaacs5b399292012-06-21 18:42:332885 " --trace-deprecation show stack traces on deprecations\n"
Tom Hughes78da9cb2010-10-18 22:50:562886 " --v8-options print v8 command line options\n"
Tom Hughes78da9cb2010-10-18 22:50:562887 " --max-stack-size=val set max v8 stack size (bytes)\n"
Steven R. Loomisac2857b2014-09-05 05:03:242888#if defined(NODE_HAVE_I18N_SUPPORT)
2889 " --icu-data-dir=dir set ICU data load path to dir\n"
2890 " (overrides NODE_ICU_DATA)\n"
2891#if !defined(NODE_HAVE_SMALL_ICU)
2892 " Note: linked-in ICU data is\n"
2893 " present.\n"
2894#endif
2895#endif
Ryan Dahl209b2192010-03-08 16:33:102896 "\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112897 "Environment variables:\n"
2898#ifdef _WIN32
2899 "NODE_PATH ';'-separated list of directories\n"
2900#else
Tom Hughes78da9cb2010-10-18 22:50:562901 "NODE_PATH ':'-separated list of directories\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112902#endif
isaacsc050d0f2011-07-25 01:04:452903 " prefixed to the module search path.\n"
Tom Hughes78da9cb2010-10-18 22:50:562904 "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
2905 " global contexts.\n"
Ryan Dahl4fa712c2011-01-13 23:28:162906 "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
Steven R. Loomisac2857b2014-09-05 05:03:242907#if defined(NODE_HAVE_I18N_SUPPORT)
2908 "NODE_ICU_DATA Data path for ICU (Intl object) data\n"
2909#if !defined(NODE_HAVE_SMALL_ICU)
2910 " (will extend linked-in data)\n"
2911#endif
2912#endif
Ryan Dahl209b2192010-03-08 16:33:102913 "\n"
Shigeki Ohtsu8440cac2015-01-14 07:39:442914 "Documentation can be found at https://iojs.org/\n");
Ryan11df2522009-08-03 16:19:402915}
2916
Miroslav Bajtoš43ec1b12013-05-02 06:34:222917
Ben Noordhuis185c5152013-09-02 14:42:012918// Parse command line arguments.
2919//
2920// argv is modified in place. exec_argv and v8_argv are out arguments that
2921// ParseArgs() allocates memory for and stores a pointer to the output
2922// vector in. The caller should free them with delete[].
2923//
2924// On exit:
2925//
2926// * argv contains the arguments with node and V8 options filtered out.
2927// * exec_argv contains both node and V8 options and nothing else.
2928// * v8_argv contains argv[0] plus any V8 options
2929static void ParseArgs(int* argc,
2930 const char** argv,
2931 int* exec_argc,
2932 const char*** exec_argv,
2933 int* v8_argc,
2934 const char*** v8_argv) {
2935 const unsigned int nargs = static_cast<unsigned int>(*argc);
2936 const char** new_exec_argv = new const char*[nargs];
2937 const char** new_v8_argv = new const char*[nargs];
2938 const char** new_argv = new const char*[nargs];
Peter Griess78d33f42010-06-04 15:29:102939
Ben Noordhuis185c5152013-09-02 14:42:012940 for (unsigned int i = 0; i < nargs; ++i) {
Ben Noordhuis2d82cdf2014-10-22 01:29:322941 new_exec_argv[i] = nullptr;
2942 new_v8_argv[i] = nullptr;
2943 new_argv[i] = nullptr;
Ben Noordhuis185c5152013-09-02 14:42:012944 }
2945
2946 // exec_argv starts with the first option, the other two start with argv[0].
2947 unsigned int new_exec_argc = 0;
2948 unsigned int new_v8_argc = 1;
2949 unsigned int new_argc = 1;
2950 new_v8_argv[0] = argv[0];
2951 new_argv[0] = argv[0];
2952
2953 unsigned int index = 1;
2954 while (index < nargs && argv[index][0] == '-') {
2955 const char* const arg = argv[index];
2956 unsigned int args_consumed = 1;
2957
Ben Noordhuisbd9c6662013-11-16 13:39:412958 if (ParseDebugOpt(arg)) {
2959 // Done, consumed by ParseDebugOpt().
Ryan1910c112009-09-11 18:05:222960 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
Ryan11df2522009-08-03 16:19:402961 printf("%s\n", NODE_VERSION);
2962 exit(0);
2963 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2964 PrintHelp();
2965 exit(0);
Ben Noordhuis185c5152013-09-02 14:42:012966 } else if (strcmp(arg, "--eval") == 0 ||
2967 strcmp(arg, "-e") == 0 ||
2968 strcmp(arg, "--print") == 0 ||
2969 strcmp(arg, "-pe") == 0 ||
Ben Noordhuisf03c3202012-09-03 14:42:182970 strcmp(arg, "-p") == 0) {
Ben Noordhuis2d82cdf2014-10-22 01:29:322971 bool is_eval = strchr(arg, 'e') != nullptr;
2972 bool is_print = strchr(arg, 'p') != nullptr;
Ben Noordhuis83b1dda2012-09-04 12:19:592973 print_eval = print_eval || is_print;
Ben Noordhuis185c5152013-09-02 14:42:012974 // --eval, -e and -pe always require an argument.
Ben Noordhuis83b1dda2012-09-04 12:19:592975 if (is_eval == true) {
Ben Noordhuis185c5152013-09-02 14:42:012976 args_consumed += 1;
2977 eval_string = argv[index + 1];
Ben Noordhuis2d82cdf2014-10-22 01:29:322978 if (eval_string == nullptr) {
Ben Noordhuis185c5152013-09-02 14:42:012979 fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
isaacsb30a03e2013-09-07 00:47:562980 exit(9);
Ben Noordhuis185c5152013-09-02 14:42:012981 }
Alexis Campailla14d6df82013-12-28 08:12:402982 } else if ((index + 1 < nargs) &&
Ben Noordhuis2d82cdf2014-10-22 01:29:322983 argv[index + 1] != nullptr &&
Alexis Campailla14d6df82013-12-28 08:12:402984 argv[index + 1][0] != '-') {
Ben Noordhuis185c5152013-09-02 14:42:012985 args_consumed += 1;
2986 eval_string = argv[index + 1];
2987 if (strncmp(eval_string, "\\-", 2) == 0) {
2988 // Starts with "\\-": escaped expression, drop the backslash.
2989 eval_string += 1;
2990 }
Ben Noordhuis83b1dda2012-09-04 12:19:592991 }
Nathan Rajlichfeaa8a42012-03-21 07:05:252992 } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
2993 force_repl = true;
isaacs5b399292012-06-21 18:42:332994 } else if (strcmp(arg, "--no-deprecation") == 0) {
isaacs5b399292012-06-21 18:42:332995 no_deprecation = true;
2996 } else if (strcmp(arg, "--trace-deprecation") == 0) {
isaacs5b399292012-06-21 18:42:332997 trace_deprecation = true;
isaacs5038f402013-03-06 01:46:372998 } else if (strcmp(arg, "--throw-deprecation") == 0) {
isaacs5038f402013-03-06 01:46:372999 throw_deprecation = true;
Ben Noordhuis185c5152013-09-02 14:42:013000 } else if (strcmp(arg, "--v8-options") == 0) {
3001 new_v8_argv[new_v8_argc] = "--help";
3002 new_v8_argc += 1;
Steven R. Loomisac2857b2014-09-05 05:03:243003#if defined(NODE_HAVE_I18N_SUPPORT)
3004 } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3005 icu_data_dir = arg + 15;
3006#endif
Ben Noordhuis185c5152013-09-02 14:42:013007 } else {
3008 // V8 option. Pass through as-is.
3009 new_v8_argv[new_v8_argc] = arg;
3010 new_v8_argc += 1;
Ryan11df2522009-08-03 16:19:403011 }
Ben Noordhuis185c5152013-09-02 14:42:013012
3013 memcpy(new_exec_argv + new_exec_argc,
3014 argv + index,
3015 args_consumed * sizeof(*argv));
3016
3017 new_exec_argc += args_consumed;
3018 index += args_consumed;
Ryan11df2522009-08-03 16:19:403019 }
Peter Griess78d33f42010-06-04 15:29:103020
Ben Noordhuis185c5152013-09-02 14:42:013021 // Copy remaining arguments.
3022 const unsigned int args_left = nargs - index;
3023 memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
3024 new_argc += args_left;
3025
3026 *exec_argc = new_exec_argc;
3027 *exec_argv = new_exec_argv;
3028 *v8_argc = new_v8_argc;
3029 *v8_argv = new_v8_argv;
3030
3031 // Copy new_argv over argv and update argc.
3032 memcpy(argv, new_argv, new_argc * sizeof(*argv));
3033 delete[] new_argv;
3034 *argc = static_cast<int>(new_argc);
Ryan11df2522009-08-03 16:19:403035}
3036
Bert Belder829735e2011-11-04 15:23:023037
Peter Rybin688859a2012-07-03 19:21:373038// Called from V8 Debug Agent TCP thread.
Fedor Indutny6a610a02014-10-04 14:44:393039static void DispatchMessagesDebugAgentCallback(Environment* env) {
3040 // TODO(indutny): move async handle to environment
Peter Rybin688859a2012-07-03 19:21:373041 uv_async_send(&dispatch_debug_messages_async);
3042}
3043
3044
Fedor Indutny6a610a02014-10-04 14:44:393045static void StartDebug(Environment* env, bool wait) {
3046 CHECK(!debugger_running);
3047
3048 env->debugger_agent()->set_dispatch_handler(
3049 DispatchMessagesDebugAgentCallback);
3050 debugger_running = env->debugger_agent()->Start(debug_port, wait);
Ben Noordhuisca363cf2013-10-15 21:32:183051 if (debugger_running == false) {
3052 fprintf(stderr, "Starting debugger on port %d failed\n", debug_port);
3053 fflush(stderr);
3054 return;
3055 }
Fedor Indutny6a610a02014-10-04 14:44:393056}
Ben Noordhuisca363cf2013-10-15 21:32:183057
Ben Noordhuisca363cf2013-10-15 21:32:183058
Fedor Indutny6a610a02014-10-04 14:44:393059// Called from the main thread.
3060static void EnableDebug(Environment* env) {
3061 CHECK(debugger_running);
Fedor Indutny8398bf92014-04-27 08:42:433062
Fedor Indutny6a610a02014-10-04 14:44:393063 // Send message to enable debug in workers
3064 HandleScope handle_scope(env->isolate());
3065
Fedor Indutnyce04c722014-03-13 16:38:143066 Local<Object> message = Object::New(env->isolate());
Ben Noordhuisca363cf2013-10-15 21:32:183067 message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
3068 FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
3069 Local<Value> argv[] = {
3070 FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
Ben Noordhuis756b6222013-08-10 22:26:113071 message
Ben Noordhuisf674b092013-08-07 19:50:413072 };
Ben Noordhuisca363cf2013-10-15 21:32:183073 MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv);
Fedor Indutny6a610a02014-10-04 14:44:393074
3075 // Enabled debugger, possibly making it wait on a semaphore
3076 env->debugger_agent()->Enable();
Miroslav Bajtoš43ec1b12013-05-02 06:34:223077}
3078
3079
Ben Noordhuisca363cf2013-10-15 21:32:183080// Called from the main thread.
Saúl Ibarra Corretgé42b93432014-03-12 23:08:293081static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {
Ben Noordhuisca363cf2013-10-15 21:32:183082 if (debugger_running == false) {
3083 fprintf(stderr, "Starting debugger agent.\n");
Fedor Indutny6a610a02014-10-04 14:44:393084
3085 Environment* env = Environment::GetCurrent(node_isolate);
3086 Context::Scope context_scope(env->context());
3087
3088 StartDebug(env, false);
3089 EnableDebug(env);
Ben Noordhuis756b6222013-08-10 22:26:113090 }
Ben Noordhuisca363cf2013-10-15 21:32:183091 Isolate::Scope isolate_scope(node_isolate);
3092 v8::Debug::ProcessDebugMessages();
Ryan Dahl2a7e7b12010-12-18 19:17:293093}
3094
3095
Fedor Indutny82d0ac72011-09-24 13:51:593096#ifdef __POSIX__
Ben Noordhuis4234bcc2013-10-16 00:54:243097static volatile sig_atomic_t caught_early_debug_signal;
3098
3099
3100static void EarlyDebugSignalHandler(int signo) {
3101 caught_early_debug_signal = 1;
3102}
3103
3104
3105static void InstallEarlyDebugSignalHandler() {
3106 struct sigaction sa;
3107 memset(&sa, 0, sizeof(sa));
3108 sa.sa_handler = EarlyDebugSignalHandler;
Ben Noordhuis2d82cdf2014-10-22 01:29:323109 sigaction(SIGUSR1, &sa, nullptr);
Ben Noordhuis4234bcc2013-10-16 00:54:243110}
3111
3112
Ben Noordhuisca363cf2013-10-15 21:32:183113static void EnableDebugSignalHandler(int signo) {
3114 // Call only async signal-safe functions here!
3115 v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3116 uv_async_send(&dispatch_debug_messages_async);
Ryan Dahl2a7e7b12010-12-18 19:17:293117}
3118
3119
Geir Haugec61b0e92014-03-31 07:52:033120static void RegisterSignalHandler(int signal,
3121 void (*handler)(int signal),
3122 bool reset_handler = false) {
Tom Hughesf61b1102010-10-12 21:01:583123 struct sigaction sa;
Tom Hughesf61b1102010-10-12 21:01:583124 memset(&sa, 0, sizeof(sa));
3125 sa.sa_handler = handler;
Geir Haugec61b0e92014-03-31 07:52:033126 sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
Tom Hughesf61b1102010-10-12 21:01:583127 sigfillset(&sa.sa_mask);
Ben Noordhuis2d82cdf2014-10-22 01:29:323128 CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
Bert Belder829735e2011-11-04 15:23:023129}
3130
3131
Ben Noordhuis110a9cd2013-07-03 02:23:443132void DebugProcess(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:553133 Environment* env = Environment::GetCurrent(args);
Bert Belder829735e2011-11-04 15:23:023134
3135 if (args.Length() != 1) {
Fedor Indutny75adde02014-02-21 13:02:423136 return env->ThrowError("Invalid number of arguments.");
Bert Belder829735e2011-11-04 15:23:023137 }
3138
3139 pid_t pid;
3140 int r;
3141
3142 pid = args[0]->IntegerValue();
3143 r = kill(pid, SIGUSR1);
3144 if (r != 0) {
Fedor Indutny75adde02014-02-21 13:02:423145 return env->ThrowErrnoException(errno, "kill");
Bert Belder829735e2011-11-04 15:23:023146 }
Tom Hughesf61b1102010-10-12 21:01:583147}
Ben Noordhuisca363cf2013-10-15 21:32:183148
3149
3150static int RegisterDebugSignalHandler() {
3151 // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3152 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
Ben Noordhuis4234bcc2013-10-16 00:54:243153 // If we caught a SIGUSR1 during the bootstrap process, re-raise it
3154 // now that the debugger infrastructure is in place.
Fedor Indutny2bc30f22013-10-16 16:57:263155 if (caught_early_debug_signal)
3156 raise(SIGUSR1);
Ben Noordhuisca363cf2013-10-15 21:32:183157 return 0;
3158}
Fedor Indutny8e29ce92013-07-31 18:07:293159#endif // __POSIX__
Tom Hughesf61b1102010-10-12 21:01:583160
3161
Bert Belder829735e2011-11-04 15:23:023162#ifdef _WIN32
3163DWORD WINAPI EnableDebugThreadProc(void* arg) {
Ben Noordhuisca363cf2013-10-15 21:32:183164 v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3165 uv_async_send(&dispatch_debug_messages_async);
Bert Belder829735e2011-11-04 15:23:023166 return 0;
3167}
3168
3169
Bert Belder8f2694b2012-02-16 21:19:483170static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
3171 size_t buf_len) {
3172 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
Bert Belder829735e2011-11-04 15:23:023173}
3174
3175
3176static int RegisterDebugSignalHandler() {
Bert Belder8f2694b2012-02-16 21:19:483177 wchar_t mapping_name[32];
Bert Belder829735e2011-11-04 15:23:023178 HANDLE mapping_handle;
3179 DWORD pid;
3180 LPTHREAD_START_ROUTINE* handler;
3181
3182 pid = GetCurrentProcessId();
3183
3184 if (GetDebugSignalHandlerMappingName(pid,
3185 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:483186 ARRAY_SIZE(mapping_name)) < 0) {
Bert Belder829735e2011-11-04 15:23:023187 return -1;
3188 }
3189
Bert Belder8f2694b2012-02-16 21:19:483190 mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
Ben Noordhuis2d82cdf2014-10-22 01:29:323191 nullptr,
Bert Belder829735e2011-11-04 15:23:023192 PAGE_READWRITE,
3193 0,
3194 sizeof *handler,
3195 mapping_name);
Ben Noordhuis2d82cdf2014-10-22 01:29:323196 if (mapping_handle == nullptr) {
Bert Belder829735e2011-11-04 15:23:023197 return -1;
3198 }
3199
Bert Belder8f2694b2012-02-16 21:19:483200 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3201 MapViewOfFile(mapping_handle,
3202 FILE_MAP_ALL_ACCESS,
3203 0,
3204 0,
3205 sizeof *handler));
Ben Noordhuis2d82cdf2014-10-22 01:29:323206 if (handler == nullptr) {
Bert Belder829735e2011-11-04 15:23:023207 CloseHandle(mapping_handle);
3208 return -1;
3209 }
3210
3211 *handler = EnableDebugThreadProc;
3212
Fedor Indutny8e29ce92013-07-31 18:07:293213 UnmapViewOfFile(static_cast<void*>(handler));
Bert Belder829735e2011-11-04 15:23:023214
3215 return 0;
3216}
3217
3218
Ben Noordhuis110a9cd2013-07-03 02:23:443219static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:553220 Environment* env = Environment::GetCurrent(args);
Alexis Campailla440b9e22014-02-24 18:55:273221 Isolate* isolate = args.GetIsolate();
Bert Belder829735e2011-11-04 15:23:023222 DWORD pid;
Ben Noordhuis2d82cdf2014-10-22 01:29:323223 HANDLE process = nullptr;
3224 HANDLE thread = nullptr;
3225 HANDLE mapping = nullptr;
Bert Belder8f2694b2012-02-16 21:19:483226 wchar_t mapping_name[32];
Ben Noordhuis2d82cdf2014-10-22 01:29:323227 LPTHREAD_START_ROUTINE* handler = nullptr;
Bert Belder829735e2011-11-04 15:23:023228
3229 if (args.Length() != 1) {
Fedor Indutny75adde02014-02-21 13:02:423230 env->ThrowError("Invalid number of arguments.");
Bert Belder829735e2011-11-04 15:23:023231 goto out;
3232 }
3233
3234 pid = (DWORD) args[0]->IntegerValue();
3235
Bert Belder68db2062012-02-03 14:37:463236 process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
Bert Belder829735e2011-11-04 15:23:023237 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
3238 PROCESS_VM_READ,
3239 FALSE,
3240 pid);
Ben Noordhuis2d82cdf2014-10-22 01:29:323241 if (process == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273242 isolate->ThrowException(
3243 WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
Bert Belder829735e2011-11-04 15:23:023244 goto out;
3245 }
3246
3247 if (GetDebugSignalHandlerMappingName(pid,
3248 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:483249 ARRAY_SIZE(mapping_name)) < 0) {
Fedor Indutny75adde02014-02-21 13:02:423250 env->ThrowErrnoException(errno, "sprintf");
Bert Belder829735e2011-11-04 15:23:023251 goto out;
3252 }
3253
Bert Belder8f2694b2012-02-16 21:19:483254 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
Ben Noordhuis2d82cdf2014-10-22 01:29:323255 if (mapping == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273256 isolate->ThrowException(WinapiErrnoException(isolate,
Fedor Indutny75adde02014-02-21 13:02:423257 GetLastError(),
3258 "OpenFileMappingW"));
Bert Belder829735e2011-11-04 15:23:023259 goto out;
3260 }
3261
Bert Belder8f2694b2012-02-16 21:19:483262 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3263 MapViewOfFile(mapping,
3264 FILE_MAP_READ,
3265 0,
3266 0,
3267 sizeof *handler));
Ben Noordhuis2d82cdf2014-10-22 01:29:323268 if (handler == nullptr || *handler == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273269 isolate->ThrowException(
3270 WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
Bert Belder829735e2011-11-04 15:23:023271 goto out;
3272 }
3273
Bert Belder68db2062012-02-03 14:37:463274 thread = CreateRemoteThread(process,
Ben Noordhuis2d82cdf2014-10-22 01:29:323275 nullptr,
Bert Belder829735e2011-11-04 15:23:023276 0,
3277 *handler,
Ben Noordhuis2d82cdf2014-10-22 01:29:323278 nullptr,
Bert Belder829735e2011-11-04 15:23:023279 0,
Ben Noordhuis2d82cdf2014-10-22 01:29:323280 nullptr);
3281 if (thread == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273282 isolate->ThrowException(WinapiErrnoException(isolate,
3283 GetLastError(),
3284 "CreateRemoteThread"));
Bert Belder829735e2011-11-04 15:23:023285 goto out;
3286 }
3287
3288 // Wait for the thread to terminate
3289 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
Alexis Campailla440b9e22014-02-24 18:55:273290 isolate->ThrowException(WinapiErrnoException(isolate,
3291 GetLastError(),
3292 "WaitForSingleObject"));
Bert Belder829735e2011-11-04 15:23:023293 goto out;
3294 }
3295
3296 out:
Ben Noordhuis2d82cdf2014-10-22 01:29:323297 if (process != nullptr)
Fedor Indutny8e29ce92013-07-31 18:07:293298 CloseHandle(process);
Ben Noordhuis2d82cdf2014-10-22 01:29:323299 if (thread != nullptr)
Bert Belder829735e2011-11-04 15:23:023300 CloseHandle(thread);
Ben Noordhuis2d82cdf2014-10-22 01:29:323301 if (handler != nullptr)
Bert Belder829735e2011-11-04 15:23:023302 UnmapViewOfFile(handler);
Ben Noordhuis2d82cdf2014-10-22 01:29:323303 if (mapping != nullptr)
Bert Belder829735e2011-11-04 15:23:023304 CloseHandle(mapping);
Bert Belder829735e2011-11-04 15:23:023305}
Fedor Indutny8e29ce92013-07-31 18:07:293306#endif // _WIN32
Bert Belder829735e2011-11-04 15:23:023307
3308
Ben Noordhuis110a9cd2013-07-03 02:23:443309static void DebugPause(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:423310 v8::Debug::DebugBreak(args.GetIsolate());
Fedor Indutnyb0388cc2011-12-10 16:52:073311}
3312
3313
Ben Noordhuis110a9cd2013-07-03 02:23:443314static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny3f43b1c2012-02-12 15:53:433315 if (debugger_running) {
Ben Noordhuisd3c317e2014-10-13 13:19:553316 Environment* env = Environment::GetCurrent(args);
Fedor Indutny6a610a02014-10-04 14:44:393317 env->debugger_agent()->Stop();
Fedor Indutny3f43b1c2012-02-12 15:53:433318 debugger_running = false;
3319 }
Fedor Indutny3f43b1c2012-02-12 15:53:433320}
3321
3322
Ben Noordhuis185c5152013-09-02 14:42:013323void Init(int* argc,
3324 const char** argv,
3325 int* exec_argc,
3326 const char*** exec_argv) {
Ben Noordhuis74a82152012-02-03 15:32:003327 // Initialize prog_start_time to get relative uptime.
Rasmus Christian Pedersen734fb492014-09-18 12:10:533328 prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
Ben Noordhuis74a82152012-02-03 15:32:003329
Bert Belder09be3602012-06-13 23:28:513330 // Make inherited handles noninheritable.
3331 uv_disable_stdio_inheritance();
3332
Miroslav Bajtošfbf46412013-05-02 14:42:493333 // init async debug messages dispatching
Ben Noordhuis756b6222013-08-10 22:26:113334 // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
Miroslav Bajtošfbf46412013-05-02 14:42:493335 uv_async_init(uv_default_loop(),
3336 &dispatch_debug_messages_async,
3337 DispatchDebugMessagesAsyncCallback);
3338 uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
3339
Ben Noordhuis490d5ab2014-03-31 12:22:493340#if defined(NODE_V8_OPTIONS)
3341 // Should come before the call to V8::SetFlagsFromCommandLine()
3342 // so the user can disable a flag --foo at run-time by passing
3343 // --no_foo from the command line.
3344 V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
3345#endif
Fedor Indutnyb55c9d62014-03-26 20:30:493346
Ryan Dahl38814552009-10-09 15:15:473347 // Parse a few arguments which are specific to Node.
Ben Noordhuis185c5152013-09-02 14:42:013348 int v8_argc;
3349 const char** v8_argv;
3350 ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
Danny Coatesdc8c0792010-08-01 22:46:483351
Ben Noordhuis9566fe82013-10-03 08:45:323352 // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
3353 // manually? That would give us a little more control over its runtime
3354 // behavior but it could also interfere with the user's intentions in ways
3355 // we fail to anticipate. Dillema.
3356 for (int i = 1; i < v8_argc; ++i) {
3357 if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
3358 v8_is_profiling = true;
3359 break;
3360 }
3361 }
3362
Steven R. Loomisac2857b2014-09-05 05:03:243363#if defined(NODE_HAVE_I18N_SUPPORT)
Ben Noordhuis2d82cdf2014-10-22 01:29:323364 if (icu_data_dir == nullptr) {
Steven R. Loomisac2857b2014-09-05 05:03:243365 // if the parameter isn't given, use the env variable.
Ben Noordhuis8f6c5872014-10-11 19:48:253366 icu_data_dir = secure_getenv("NODE_ICU_DATA");
Steven R. Loomisac2857b2014-09-05 05:03:243367 }
3368 // Initialize ICU.
Ben Noordhuis2d82cdf2014-10-22 01:29:323369 // If icu_data_dir is nullptr here, it will load the 'minimal' data.
Steven R. Loomisac2857b2014-09-05 05:03:243370 if (!i18n::InitializeICUDirectory(icu_data_dir)) {
Ben Noordhuis2d82cdf2014-10-22 01:29:323371 FatalError(nullptr, "Could not initialize ICU "
Steven R. Loomisac2857b2014-09-05 05:03:243372 "(check NODE_ICU_DATA or --icu-data-dir parameters)");
3373 }
3374#endif
Ben Noordhuis185c5152013-09-02 14:42:013375 // The const_cast doesn't violate conceptual const-ness. V8 doesn't modify
3376 // the argv array or the elements it points to.
3377 V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
3378
3379 // Anything that's still in v8_argv is not a V8 or a node option.
3380 for (int i = 1; i < v8_argc; i++) {
3381 fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
3382 }
3383 delete[] v8_argv;
Ben Noordhuis2d82cdf2014-10-22 01:29:323384 v8_argv = nullptr;
Ben Noordhuis185c5152013-09-02 14:42:013385
3386 if (v8_argc > 1) {
isaacsb30a03e2013-09-07 00:47:563387 exit(9);
Ryan Dahladec5442010-08-04 17:38:193388 }
Tom Hughes78da9cb2010-10-18 22:50:563389
Ben Noordhuis185c5152013-09-02 14:42:013390 if (debug_wait_connect) {
3391 const char expose_debug_as[] = "--expose_debug_as=v8debug";
3392 V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
3393 }
Ryan23376302009-09-10 10:34:293394
Ben Noordhuis0693d222013-06-29 06:16:253395 V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton);
3396
Bert Belder30bab522010-11-25 00:09:063397#ifdef __POSIX__
Ben Noordhuis68200542013-10-02 10:17:573398 // Raise the open file descriptor limit.
Trevor Norris7503e4c2013-10-04 03:43:353399 { // NOLINT (whitespace/braces)
Ben Noordhuis68200542013-10-02 10:17:573400 struct rlimit lim;
3401 if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
3402 // Do a binary search for the limit.
3403 rlim_t min = lim.rlim_cur;
3404 rlim_t max = 1 << 20;
3405 // But if there's a defined upper bound, don't search, just set it.
3406 if (lim.rlim_max != RLIM_INFINITY) {
3407 min = lim.rlim_max;
3408 max = lim.rlim_max;
3409 }
3410 do {
3411 lim.rlim_cur = min + (max - min) / 2;
3412 if (setrlimit(RLIMIT_NOFILE, &lim)) {
3413 max = lim.rlim_cur;
3414 } else {
3415 min = lim.rlim_cur;
3416 }
3417 } while (min + 1 < max);
3418 }
3419 }
Ryan Dahlb6c5cf62010-05-04 17:41:563420 // Ignore SIGPIPE
Tom Hughesf61b1102010-10-12 21:01:583421 RegisterSignalHandler(SIGPIPE, SIG_IGN);
Geir Haugec61b0e92014-03-31 07:52:033422 RegisterSignalHandler(SIGINT, SignalExit, true);
3423 RegisterSignalHandler(SIGTERM, SignalExit, true);
Fedor Indutny8e29ce92013-07-31 18:07:293424#endif // __POSIX__
Ryan Dahlb6c5cf62010-05-04 17:41:563425
Fedor Indutny6a610a02014-10-04 14:44:393426 if (!use_debug_agent) {
Ben Noordhuis74a82152012-02-03 15:32:003427 RegisterDebugSignalHandler();
Ben Noordhuis74a82152012-02-03 15:32:003428 }
Cheng Zhao22e1aea2015-01-12 21:31:253429
3430 // We should set node_is_initialized here instead of in node::Start,
3431 // otherwise embedders using node::Init to initialize everything will not be
3432 // able to set it and native modules will not load for them.
3433 node_is_initialized = true;
Ben Noordhuis5866f1a2011-12-09 18:02:333434}
Ben Noordhuis356992f2011-11-22 16:10:093435
Ben Noordhuis5866f1a2011-12-09 18:02:333436
Ben Noordhuise4a8d262012-04-21 05:13:253437struct AtExitCallback {
3438 AtExitCallback* next_;
3439 void (*cb_)(void* arg);
3440 void* arg_;
3441};
3442
3443static AtExitCallback* at_exit_functions_;
3444
3445
Ben Noordhuis756b6222013-08-10 22:26:113446// TODO(bnoordhuis) Turn into per-context event.
3447void RunAtExit(Environment* env) {
Ben Noordhuise4a8d262012-04-21 05:13:253448 AtExitCallback* p = at_exit_functions_;
Ben Noordhuis2d82cdf2014-10-22 01:29:323449 at_exit_functions_ = nullptr;
Ben Noordhuise4a8d262012-04-21 05:13:253450
3451 while (p) {
3452 AtExitCallback* q = p->next_;
3453 p->cb_(p->arg_);
3454 delete p;
3455 p = q;
3456 }
3457}
3458
3459
3460void AtExit(void (*cb)(void* arg), void* arg) {
3461 AtExitCallback* p = new AtExitCallback;
3462 p->cb_ = cb;
3463 p->arg_ = arg;
3464 p->next_ = at_exit_functions_;
3465 at_exit_functions_ = p;
3466}
3467
3468
Ben Noordhuisa2eeb432013-10-07 13:39:393469void EmitBeforeExit(Environment* env) {
3470 Context::Scope context_scope(env->context());
3471 HandleScope handle_scope(env->isolate());
3472 Local<Object> process_object = env->process_object();
3473 Local<String> exit_code = FIXED_ONE_BYTE_STRING(env->isolate(), "exitCode");
3474 Local<Value> args[] = {
3475 FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
Trevor Norrisd5533862015-01-07 21:29:583476 process_object->Get(exit_code)->ToInteger(env->isolate())
Ben Noordhuisa2eeb432013-10-07 13:39:393477 };
3478 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3479}
3480
3481
Fedor Indutnye57ab7b2014-01-18 22:49:333482int EmitExit(Environment* env) {
Ben Noordhuis5866f1a2011-12-09 18:02:333483 // process.emit('exit')
Ben Noordhuis756b6222013-08-10 22:26:113484 HandleScope handle_scope(env->isolate());
Ben Noordhuis27f115d2013-11-11 09:53:003485 Context::Scope context_scope(env->context());
Ben Noordhuis756b6222013-08-10 22:26:113486 Local<Object> process_object = env->process_object();
Fedor Indutny75adde02014-02-21 13:02:423487 process_object->Set(env->exiting_string(), True(env->isolate()));
isaacsa5dba822013-09-06 23:46:353488
Fedor Indutny75adde02014-02-21 13:02:423489 Handle<String> exitCode = env->exit_code_string();
Rasmus Christian Pedersen734fb492014-09-18 12:10:533490 int code = process_object->Get(exitCode)->Int32Value();
isaacsa5dba822013-09-06 23:46:353491
Ben Noordhuisf674b092013-08-07 19:50:413492 Local<Value> args[] = {
Fedor Indutny75adde02014-02-21 13:02:423493 env->exit_string(),
Fedor Indutnyce04c722014-03-13 16:38:143494 Integer::New(env->isolate(), code)
Ben Noordhuisf674b092013-08-07 19:50:413495 };
isaacsa5dba822013-09-06 23:46:353496
Ben Noordhuis756b6222013-08-10 22:26:113497 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
Fedor Indutnyc0d81f92014-02-09 10:40:573498
3499 // Reload exit code, it may be changed by `emit('exit')`
Rasmus Christian Pedersen734fb492014-09-18 12:10:533500 return process_object->Get(exitCode)->Int32Value();
Ben Noordhuis756b6222013-08-10 22:26:113501}
3502
3503
Fedor Indutny6a610a02014-10-04 14:44:393504// Just a convenience method
Ben Noordhuis756b6222013-08-10 22:26:113505Environment* CreateEnvironment(Isolate* isolate,
Dean McNameeda30c002014-07-09 11:36:503506 Handle<Context> context,
Ben Noordhuis756b6222013-08-10 22:26:113507 int argc,
3508 const char* const* argv,
3509 int exec_argc,
3510 const char* const* exec_argv) {
Fedor Indutny6a610a02014-10-04 14:44:393511 Environment* env;
3512 Context::Scope context_scope(context);
3513
3514 env = CreateEnvironment(isolate,
3515 uv_default_loop(),
3516 context,
3517 argc,
3518 argv,
3519 exec_argc,
3520 exec_argv);
3521
3522 LoadEnvironment(env);
3523
3524 return env;
3525}
3526
3527
3528static void HandleCloseCb(uv_handle_t* handle) {
3529 Environment* env = reinterpret_cast<Environment*>(handle->data);
3530 env->FinishHandleCleanup(handle);
3531}
3532
3533
3534static void HandleCleanup(Environment* env,
3535 uv_handle_t* handle,
3536 void* arg) {
3537 handle->data = env;
3538 uv_close(handle, HandleCloseCb);
3539}
3540
3541
3542Environment* CreateEnvironment(Isolate* isolate,
3543 uv_loop_t* loop,
3544 Handle<Context> context,
3545 int argc,
3546 const char* const* argv,
3547 int exec_argc,
3548 const char* const* exec_argv) {
Ben Noordhuis756b6222013-08-10 22:26:113549 HandleScope handle_scope(isolate);
3550
Ben Noordhuis756b6222013-08-10 22:26:113551 Context::Scope context_scope(context);
Fedor Indutny6a610a02014-10-04 14:44:393552 Environment* env = Environment::New(context, loop);
Ben Noordhuis756b6222013-08-10 22:26:113553
Vladimir Kurchatkin8dc6be12014-09-22 16:19:503554 isolate->SetAutorunMicrotasks(false);
3555
Ben Noordhuis756b6222013-08-10 22:26:113556 uv_check_init(env->event_loop(), env->immediate_check_handle());
3557 uv_unref(
3558 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
Fedor Indutny6a610a02014-10-04 14:44:393559
Ben Noordhuis756b6222013-08-10 22:26:113560 uv_idle_init(env->event_loop(), env->immediate_idle_handle());
3561
Ben Noordhuis57231d52013-10-02 04:37:443562 // Inform V8's CPU profiler when we're idle. The profiler is sampling-based
3563 // but not all samples are created equal; mark the wall clock time spent in
3564 // epoll_wait() and friends so profiling tools can filter it out. The samples
3565 // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
Ben Noordhuis57231d52013-10-02 04:37:443566 // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
3567 // probably fortify in the API contract, namely that the last started prepare
3568 // or check watcher runs first. It's not 100% foolproof; if an add-on starts
3569 // a prepare or check watcher after us, any samples attributed to its callback
3570 // will be recorded with state=IDLE.
3571 uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
Ben Noordhuis58729f12013-10-03 17:27:513572 uv_check_init(env->event_loop(), env->idle_check_handle());
Ben Noordhuis57231d52013-10-02 04:37:443573 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
Ben Noordhuis57231d52013-10-02 04:37:443574 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
3575
Fedor Indutny6a610a02014-10-04 14:44:393576 // Register handle cleanups
3577 env->RegisterHandleCleanup(
3578 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()),
3579 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323580 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393581 env->RegisterHandleCleanup(
3582 reinterpret_cast<uv_handle_t*>(env->immediate_idle_handle()),
3583 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323584 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393585 env->RegisterHandleCleanup(
3586 reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()),
3587 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323588 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393589 env->RegisterHandleCleanup(
3590 reinterpret_cast<uv_handle_t*>(env->idle_check_handle()),
3591 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323592 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393593
Ben Noordhuis9566fe82013-10-03 08:45:323594 if (v8_is_profiling) {
Ben Noordhuis58729f12013-10-03 17:27:513595 StartProfilerIdleNotifier(env);
Ben Noordhuis9566fe82013-10-03 08:45:323596 }
3597
Fedor Indutnyce04c722014-03-13 16:38:143598 Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
Ben Noordhuisf6496262013-10-03 09:03:463599 process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
3600
3601 Local<Object> process_object = process_template->GetFunction()->NewInstance();
3602 env->set_process_object(process_object);
3603
3604 SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
Ben Noordhuisf6496262013-10-03 09:03:463605
Ben Noordhuis756b6222013-08-10 22:26:113606 return env;
Ben Noordhuis5866f1a2011-12-09 18:02:333607}
3608
Micheil Smith19fd5302012-03-05 17:53:153609
Ben Noordhuis185c5152013-09-02 14:42:013610int Start(int argc, char** argv) {
Ben Noordhuis8f6c5872014-10-11 19:48:253611 const char* replaceInvalid = secure_getenv("NODE_INVALID_UTF8");
Felix Geisendörfer0da4c672014-01-20 08:47:193612
Ben Noordhuis2d82cdf2014-10-22 01:29:323613 if (replaceInvalid == nullptr)
Felix Geisendörfer0da4c672014-01-20 08:47:193614 WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8;
3615
Ben Noordhuis4234bcc2013-10-16 00:54:243616#if !defined(_WIN32)
3617 // Try hard not to lose SIGUSR1 signals during the bootstrap process.
3618 InstallEarlyDebugSignalHandler();
3619#endif
3620
Ben Noordhuis5fdff382014-10-11 14:52:073621 CHECK_GT(argc, 0);
Micheil Smith19fd5302012-03-05 17:53:153622
Ben Noordhuis185c5152013-09-02 14:42:013623 // Hack around with the argv pointer. Used for process.title = "blah".
Ben Noordhuis1a979982012-03-15 22:10:323624 argv = uv_setup_args(argc, argv);
3625
Ben Noordhuis185c5152013-09-02 14:42:013626 // This needs to run *before* V8::Initialize(). The const_cast is not
3627 // optional, in case you're wondering.
3628 int exec_argc;
3629 const char** exec_argv;
3630 Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
Ben Noordhuis5866f1a2011-12-09 18:02:333631
Ben Noordhuis7ac23912013-09-20 20:01:493632#if HAVE_OPENSSL
3633 // V8 on Windows doesn't have a good source of entropy. Seed it from
3634 // OpenSSL's pool.
3635 V8::SetEntropySource(crypto::EntropySource);
3636#endif
3637
Fedor Indutny50839a02014-10-10 22:17:033638 V8::InitializePlatform(new Platform(4));
3639
Fedor Indutnye57ab7b2014-01-18 22:49:333640 int code;
Ben Noordhuis75ea5662013-09-23 12:27:263641 V8::Initialize();
Fedor Indutny50839a02014-10-10 22:17:033642
3643 // Fetch a reference to the main isolate, so we have a reference to it
3644 // even when we need it to access it from another (debugger) thread.
3645 node_isolate = Isolate::New();
Marcel Laverdetc33d3172012-05-04 22:29:423646 {
Trevor Norris0bba5902013-03-18 20:54:003647 Locker locker(node_isolate);
Ben Noordhuis437c2f42014-08-19 17:28:063648 Isolate::Scope isolate_scope(node_isolate);
Dean McNameeda30c002014-07-09 11:36:503649 HandleScope handle_scope(node_isolate);
3650 Local<Context> context = Context::New(node_isolate);
3651 Environment* env = CreateEnvironment(
Fedor Indutny6a610a02014-10-04 14:44:393652 node_isolate,
3653 uv_default_loop(),
3654 context,
3655 argc,
3656 argv,
3657 exec_argc,
3658 exec_argv);
3659 Context::Scope context_scope(context);
Fedor Indutny5596f932014-02-28 13:25:283660
Fedor Indutny6a610a02014-10-04 14:44:393661 // Start debug agent when argv has --debug
3662 if (use_debug_agent)
3663 StartDebug(env, debug_wait_connect);
3664
3665 LoadEnvironment(env);
3666
3667 // Enable debugger
3668 if (use_debug_agent)
3669 EnableDebug(env);
3670
3671 bool more;
3672 do {
3673 more = uv_run(env->event_loop(), UV_RUN_ONCE);
3674 if (more == false) {
3675 EmitBeforeExit(env);
3676
3677 // Emit `beforeExit` if the loop became alive either after emitting
3678 // event, or after running some callbacks.
3679 more = uv_loop_alive(env->event_loop());
3680 if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
3681 more = true;
3682 }
3683 } while (more == true);
3684 code = EmitExit(env);
3685 RunAtExit(env);
3686
Ben Noordhuis756b6222013-08-10 22:26:113687 env->Dispose();
Ben Noordhuis2d82cdf2014-10-22 01:29:323688 env = nullptr;
Marcel Laverdetc33d3172012-05-04 22:29:423689 }
3690
Ben Noordhuis2d82cdf2014-10-22 01:29:323691 CHECK_NE(node_isolate, nullptr);
Ben Noordhuis6f952842014-05-22 23:08:273692 node_isolate->Dispose();
Ben Noordhuis2d82cdf2014-10-22 01:29:323693 node_isolate = nullptr;
Ryan27b268b2009-06-17 13:05:443694 V8::Dispose();
Igor Zinkovskya58b6432011-07-07 20:54:303695
Ben Noordhuis185c5152013-09-02 14:42:013696 delete[] exec_argv;
Ben Noordhuis2d82cdf2014-10-22 01:29:323697 exec_argv = nullptr;
Micheil Smith19fd5302012-03-05 17:53:153698
Fedor Indutnye57ab7b2014-01-18 22:49:333699 return code;
Ryan19478ed2009-03-03 00:56:153700}
Ryan Dahl124fbed2010-09-19 20:13:573701
3702
3703} // namespace node