blob: fd65fbff0bddf310bd098f6d25cebc126a0a38a8 [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
Glen Keane5e825d12015-01-22 12:35:1626#if defined HAVE_LTTNG
27#include "node_lttng.h"
28#endif
29
Bert Belder22d03c92012-08-06 23:48:1530#include "ares.h"
Trevor Norrisefa62fd2013-09-24 21:12:1131#include "async-wrap.h"
32#include "async-wrap-inl.h"
Ben Noordhuis756b6222013-08-10 22:26:1133#include "env.h"
34#include "env-inl.h"
Ben Noordhuis02cab972013-07-31 21:16:0835#include "handle_wrap.h"
36#include "req_wrap.h"
37#include "string_bytes.h"
Timothy J Fontaine1a09da62014-06-10 23:36:0438#include "util.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1139#include "uv.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1140#include "v8-debug.h"
Ben Noordhuis57231d52013-10-02 04:37:4441#include "v8-profiler.h"
Ben Noordhuis02cab972013-07-31 21:16:0842#include "zlib.h"
Ryan Dahl4635ed72010-03-11 20:40:1943
Ben Noordhuis02cab972013-07-31 21:16:0844#include <errno.h>
45#include <limits.h> // PATH_MAX
Bert Beldere0f47be2011-01-17 23:22:3646#include <locale.h>
Bert Belder9cec08e2011-05-23 23:42:2247#include <signal.h>
Ryan19478ed2009-03-03 00:56:1548#include <stdio.h>
Ryan34a6f102009-05-28 12:47:1649#include <stdlib.h>
Ryan Dahlc90e44e2010-05-10 23:38:4750#include <string.h>
Ben Noordhuis02cab972013-07-31 21:16:0851#include <sys/types.h>
52
53#if defined(_MSC_VER)
Peter Bright13d6a1f2011-08-06 04:23:2554#include <direct.h>
Peter Brightb9d77772011-08-11 01:45:5655#include <io.h>
Ben Noordhuis02cab972013-07-31 21:16:0856#include <process.h>
Ben Noordhuis02cab972013-07-31 21:16:0857#define strcasecmp _stricmp
58#define getpid _getpid
Peter Brightb9d77772011-08-11 01:45:5659#define umask _umask
60typedef int mode_t;
Ben Noordhuis02cab972013-07-31 21:16:0861#else
Ben Noordhuis68200542013-10-02 10:17:5762#include <sys/resource.h> // getrlimit, setrlimit
Ben Noordhuis02cab972013-07-31 21:16:0863#include <unistd.h> // setuid, getuid
Peter Bright13d6a1f2011-08-06 04:23:2564#endif
Ryane02b71e2009-03-03 23:31:3765
Linus Mårtensson5e4e8ec2013-05-08 12:10:0766#if defined(__POSIX__) && !defined(__ANDROID__)
Ben Noordhuis02cab972013-07-31 21:16:0867#include <pwd.h> // getpwnam()
68#include <grp.h> // getgrnam()
Bert Beldera177d602010-11-25 00:02:5569#endif
70
Fedor Indutny8e29ce92013-07-31 18:07:2971#ifdef __APPLE__
Ben Noordhuis02cab972013-07-31 21:16:0872#include <crt_externs.h>
73#define environ (*_NSGetEnviron())
Fedor Indutny8e29ce92013-07-31 18:07:2974#elif !defined(_MSC_VER)
Ryan3e4fc9f2009-09-10 14:48:3875extern char **environ;
Fedor Indutny8e29ce92013-07-31 18:07:2976#endif
Ryan3e4fc9f2009-09-10 14:48:3877
Ryand6c9d312009-09-11 14:02:2978namespace node {
79
Ben Noordhuis110a9cd2013-07-03 02:23:4480using v8::Array;
Ben Noordhuis0693d222013-06-29 06:16:2581using v8::ArrayBuffer;
Ben Noordhuis110a9cd2013-07-03 02:23:4482using v8::Boolean;
83using v8::Context;
Fedor Indutnyce04c722014-03-13 16:38:1484using v8::EscapableHandleScope;
Ben Noordhuis110a9cd2013-07-03 02:23:4485using v8::Exception;
86using v8::Function;
87using v8::FunctionCallbackInfo;
88using v8::FunctionTemplate;
Ben Noordhuis511af4d2013-07-30 19:28:4389using v8::Handle;
Ben Noordhuis110a9cd2013-07-03 02:23:4490using v8::HandleScope;
91using v8::HeapStatistics;
92using v8::Integer;
93using v8::Isolate;
Ben Noordhuis511af4d2013-07-30 19:28:4394using v8::Local;
Ben Noordhuis110a9cd2013-07-03 02:23:4495using v8::Locker;
96using v8::Message;
97using v8::Number;
98using v8::Object;
99using v8::ObjectTemplate;
Ben Noordhuis110a9cd2013-07-03 02:23:44100using v8::PropertyCallbackInfo;
Ben Noordhuis511af4d2013-07-30 19:28:43101using v8::String;
Ben Noordhuis110a9cd2013-07-03 02:23:44102using v8::TryCatch;
103using v8::Uint32;
104using v8::V8;
105using v8::Value;
Trevor Norrisbdc2ea42014-10-08 08:34:46106using v8::kExternalUint32Array;
Ben Noordhuis110a9cd2013-07-03 02:23:44107
Ben Noordhuis74a82152012-02-03 15:32:00108static bool print_eval = false;
Nathan Rajlichfeaa8a42012-03-21 07:05:25109static bool force_repl = false;
isaacs5b399292012-06-21 18:42:33110static bool trace_deprecation = false;
isaacs5038f402013-03-06 01:46:37111static bool throw_deprecation = false;
Ben Noordhuis2d82cdf2014-10-22 01:29:32112static const char* eval_string = nullptr;
Ben Noordhuis74a82152012-02-03 15:32:00113static bool use_debug_agent = false;
114static bool debug_wait_connect = false;
Fedor Indutny8e29ce92013-07-31 18:07:29115static int debug_port = 5858;
Ben Noordhuis9566fe82013-10-03 08:45:32116static bool v8_is_profiling = false;
Thorsten Lorenz0fe7a0d2014-09-15 17:00:22117static bool node_is_initialized = false;
Keith M Wesolowski76b98462013-12-17 00:00:44118static node_module* modpending;
119static node_module* modlist_builtin;
Thorsten Lorenz0fe7a0d2014-09-15 17:00:22120static node_module* modlist_linked;
Keith M Wesolowski76b98462013-12-17 00:00:44121static node_module* modlist_addon;
Ben Noordhuis74a82152012-02-03 15:32:00122
Steven R. Loomisac2857b2014-09-05 05:03:24123#if defined(NODE_HAVE_I18N_SUPPORT)
124// Path to ICU data (for i18n / Intl)
Ben Noordhuis2d82cdf2014-10-22 01:29:32125static const char* icu_data_dir = nullptr;
Steven R. Loomisac2857b2014-09-05 05:03:24126#endif
127
isaacs48c3d202012-06-21 19:20:23128// used by C++ modules as well
129bool no_deprecation = false;
130
Ben Noordhuis74a82152012-02-03 15:32:00131// process-relative uptime base, initialized at start-up
132static double prog_start_time;
Ben Noordhuisca363cf2013-10-15 21:32:18133static bool debugger_running;
Ben Noordhuis5d0816b2013-01-06 22:06:48134static uv_async_t dispatch_debug_messages_async;
135
Ben Noordhuis2d82cdf2014-10-22 01:29:32136static Isolate* node_isolate = nullptr;
Ben Noordhuis5d0816b2013-01-06 22:06:48137
Felix Geisendörfer0da4c672014-01-20 08:47:19138int WRITE_UTF8_FLAGS = v8::String::HINT_MANY_WRITES_EXPECTED |
139 v8::String::NO_NULL_TERMINATION;
Ryan Dahlf80cc692010-01-06 09:17:58140
Ben Noordhuis0693d222013-06-29 06:16:25141class ArrayBufferAllocator : public ArrayBuffer::Allocator {
Fedor Indutny8e29ce92013-07-31 18:07:29142 public:
Ben Noordhuis0693d222013-06-29 06:16:25143 // Impose an upper limit to avoid out of memory errors that bring down
144 // the process.
145 static const size_t kMaxLength = 0x3fffffff;
146 static ArrayBufferAllocator the_singleton;
Ben Noordhuis5ab87db2014-10-22 02:53:26147 virtual ~ArrayBufferAllocator() = default;
Ben Noordhuis9f5800a2014-10-22 02:26:25148 virtual void* Allocate(size_t length) override;
149 virtual void* AllocateUninitialized(size_t length) override;
150 virtual void Free(void* data, size_t length) override;
Fedor Indutny8e29ce92013-07-31 18:07:29151 private:
Ben Noordhuis5ab87db2014-10-22 02:53:26152 ArrayBufferAllocator() = default;
Ben Noordhuisc038dcc2014-10-22 02:33:01153 DISALLOW_COPY_AND_ASSIGN(ArrayBufferAllocator);
Ben Noordhuis0693d222013-06-29 06:16:25154};
155
156ArrayBufferAllocator ArrayBufferAllocator::the_singleton;
157
158
159void* ArrayBufferAllocator::Allocate(size_t length) {
Fedor Indutny2bc30f22013-10-16 16:57:26160 if (length > kMaxLength)
Ben Noordhuis2d82cdf2014-10-22 01:29:32161 return nullptr;
Trevor Norris72225392013-12-10 01:11:38162 char* data = new char[length];
163 memset(data, 0, length);
164 return data;
Ben Noordhuis0693d222013-06-29 06:16:25165}
166
167
Ben Noordhuisef4a35b2013-10-22 22:17:45168void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
169 if (length > kMaxLength)
Ben Noordhuis2d82cdf2014-10-22 01:29:32170 return nullptr;
Ben Noordhuisef4a35b2013-10-22 22:17:45171 return new char[length];
172}
173
174
175void ArrayBufferAllocator::Free(void* data, size_t length) {
Ben Noordhuis0693d222013-06-29 06:16:25176 delete[] static_cast<char*>(data);
177}
178
179
Saúl Ibarra Corretgé42b93432014-03-12 23:08:29180static void CheckImmediate(uv_check_t* handle) {
Ben Noordhuis756b6222013-08-10 22:26:11181 Environment* env = Environment::from_immediate_check_handle(handle);
Fedor Indutny75adde02014-02-21 13:02:42182 HandleScope scope(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:11183 Context::Scope context_scope(env->context());
184 MakeCallback(env, env->process_object(), env->immediate_callback_string());
Shigeki Ohtsucd372512013-02-06 02:13:02185}
186
187
Saúl Ibarra Corretgé42b93432014-03-12 23:08:29188static void IdleImmediateDummy(uv_idle_t* handle) {
Ben Noordhuis756b6222013-08-10 22:26:11189 // Do nothing. Only for maintaining event loop.
Ben Noordhuis2d82cdf2014-10-22 01:29:32190 // TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
Shigeki Ohtsucd372512013-02-06 02:13:02191}
192
193
Ryan Dahlc9e27b12010-04-23 00:53:45194static inline const char *errno_string(int errorno) {
195#define ERRNO_CASE(e) case e: return #e;
196 switch (errorno) {
Ryan Dahlc9e27b12010-04-23 00:53:45197#ifdef EACCES
198 ERRNO_CASE(EACCES);
199#endif
200
201#ifdef EADDRINUSE
202 ERRNO_CASE(EADDRINUSE);
203#endif
204
205#ifdef EADDRNOTAVAIL
206 ERRNO_CASE(EADDRNOTAVAIL);
207#endif
208
209#ifdef EAFNOSUPPORT
210 ERRNO_CASE(EAFNOSUPPORT);
211#endif
212
213#ifdef EAGAIN
214 ERRNO_CASE(EAGAIN);
Ryan Dahl9b2aac62010-04-28 19:58:00215#endif
216
217#ifdef EWOULDBLOCK
218# if EAGAIN != EWOULDBLOCK
Ryan Dahlc9e27b12010-04-23 00:53:45219 ERRNO_CASE(EWOULDBLOCK);
220# endif
221#endif
222
223#ifdef EALREADY
224 ERRNO_CASE(EALREADY);
225#endif
226
227#ifdef EBADF
228 ERRNO_CASE(EBADF);
229#endif
230
231#ifdef EBADMSG
232 ERRNO_CASE(EBADMSG);
233#endif
234
235#ifdef EBUSY
236 ERRNO_CASE(EBUSY);
237#endif
238
239#ifdef ECANCELED
240 ERRNO_CASE(ECANCELED);
241#endif
242
243#ifdef ECHILD
244 ERRNO_CASE(ECHILD);
245#endif
246
247#ifdef ECONNABORTED
248 ERRNO_CASE(ECONNABORTED);
249#endif
250
251#ifdef ECONNREFUSED
252 ERRNO_CASE(ECONNREFUSED);
253#endif
254
255#ifdef ECONNRESET
256 ERRNO_CASE(ECONNRESET);
257#endif
258
259#ifdef EDEADLK
260 ERRNO_CASE(EDEADLK);
261#endif
262
263#ifdef EDESTADDRREQ
264 ERRNO_CASE(EDESTADDRREQ);
265#endif
266
267#ifdef EDOM
268 ERRNO_CASE(EDOM);
269#endif
270
271#ifdef EDQUOT
272 ERRNO_CASE(EDQUOT);
273#endif
274
275#ifdef EEXIST
276 ERRNO_CASE(EEXIST);
277#endif
278
279#ifdef EFAULT
280 ERRNO_CASE(EFAULT);
281#endif
282
283#ifdef EFBIG
284 ERRNO_CASE(EFBIG);
285#endif
286
287#ifdef EHOSTUNREACH
288 ERRNO_CASE(EHOSTUNREACH);
289#endif
290
291#ifdef EIDRM
292 ERRNO_CASE(EIDRM);
293#endif
294
295#ifdef EILSEQ
296 ERRNO_CASE(EILSEQ);
297#endif
298
299#ifdef EINPROGRESS
300 ERRNO_CASE(EINPROGRESS);
301#endif
302
303#ifdef EINTR
304 ERRNO_CASE(EINTR);
305#endif
306
307#ifdef EINVAL
308 ERRNO_CASE(EINVAL);
309#endif
310
311#ifdef EIO
312 ERRNO_CASE(EIO);
313#endif
314
315#ifdef EISCONN
316 ERRNO_CASE(EISCONN);
317#endif
318
319#ifdef EISDIR
320 ERRNO_CASE(EISDIR);
321#endif
322
323#ifdef ELOOP
324 ERRNO_CASE(ELOOP);
325#endif
326
327#ifdef EMFILE
328 ERRNO_CASE(EMFILE);
329#endif
330
331#ifdef EMLINK
332 ERRNO_CASE(EMLINK);
333#endif
334
335#ifdef EMSGSIZE
336 ERRNO_CASE(EMSGSIZE);
337#endif
338
339#ifdef EMULTIHOP
340 ERRNO_CASE(EMULTIHOP);
341#endif
342
343#ifdef ENAMETOOLONG
344 ERRNO_CASE(ENAMETOOLONG);
345#endif
346
347#ifdef ENETDOWN
348 ERRNO_CASE(ENETDOWN);
349#endif
350
351#ifdef ENETRESET
352 ERRNO_CASE(ENETRESET);
353#endif
354
355#ifdef ENETUNREACH
356 ERRNO_CASE(ENETUNREACH);
357#endif
358
359#ifdef ENFILE
360 ERRNO_CASE(ENFILE);
361#endif
362
363#ifdef ENOBUFS
364 ERRNO_CASE(ENOBUFS);
365#endif
366
367#ifdef ENODATA
368 ERRNO_CASE(ENODATA);
369#endif
370
371#ifdef ENODEV
372 ERRNO_CASE(ENODEV);
373#endif
374
375#ifdef ENOENT
376 ERRNO_CASE(ENOENT);
377#endif
378
379#ifdef ENOEXEC
380 ERRNO_CASE(ENOEXEC);
381#endif
382
Ryan Dahlc9e27b12010-04-23 00:53:45383#ifdef ENOLINK
384 ERRNO_CASE(ENOLINK);
385#endif
386
Ryan Dahl3bb21b52010-04-28 22:07:15387#ifdef ENOLCK
388# if ENOLINK != ENOLCK
389 ERRNO_CASE(ENOLCK);
390# endif
391#endif
392
Ryan Dahlc9e27b12010-04-23 00:53:45393#ifdef ENOMEM
394 ERRNO_CASE(ENOMEM);
395#endif
396
397#ifdef ENOMSG
398 ERRNO_CASE(ENOMSG);
399#endif
400
401#ifdef ENOPROTOOPT
402 ERRNO_CASE(ENOPROTOOPT);
403#endif
404
405#ifdef ENOSPC
406 ERRNO_CASE(ENOSPC);
407#endif
408
409#ifdef ENOSR
410 ERRNO_CASE(ENOSR);
411#endif
412
413#ifdef ENOSTR
414 ERRNO_CASE(ENOSTR);
415#endif
416
417#ifdef ENOSYS
418 ERRNO_CASE(ENOSYS);
419#endif
420
421#ifdef ENOTCONN
422 ERRNO_CASE(ENOTCONN);
423#endif
424
425#ifdef ENOTDIR
426 ERRNO_CASE(ENOTDIR);
427#endif
428
429#ifdef ENOTEMPTY
430 ERRNO_CASE(ENOTEMPTY);
431#endif
432
433#ifdef ENOTSOCK
434 ERRNO_CASE(ENOTSOCK);
435#endif
436
437#ifdef ENOTSUP
438 ERRNO_CASE(ENOTSUP);
439#else
440# ifdef EOPNOTSUPP
441 ERRNO_CASE(EOPNOTSUPP);
442# endif
443#endif
444
445#ifdef ENOTTY
446 ERRNO_CASE(ENOTTY);
447#endif
448
449#ifdef ENXIO
450 ERRNO_CASE(ENXIO);
451#endif
452
453
454#ifdef EOVERFLOW
455 ERRNO_CASE(EOVERFLOW);
456#endif
457
458#ifdef EPERM
459 ERRNO_CASE(EPERM);
460#endif
461
462#ifdef EPIPE
463 ERRNO_CASE(EPIPE);
464#endif
465
466#ifdef EPROTO
467 ERRNO_CASE(EPROTO);
468#endif
469
470#ifdef EPROTONOSUPPORT
471 ERRNO_CASE(EPROTONOSUPPORT);
472#endif
473
474#ifdef EPROTOTYPE
475 ERRNO_CASE(EPROTOTYPE);
476#endif
477
478#ifdef ERANGE
479 ERRNO_CASE(ERANGE);
480#endif
481
482#ifdef EROFS
483 ERRNO_CASE(EROFS);
484#endif
485
486#ifdef ESPIPE
487 ERRNO_CASE(ESPIPE);
488#endif
489
490#ifdef ESRCH
491 ERRNO_CASE(ESRCH);
492#endif
493
494#ifdef ESTALE
495 ERRNO_CASE(ESTALE);
496#endif
497
498#ifdef ETIME
499 ERRNO_CASE(ETIME);
500#endif
501
502#ifdef ETIMEDOUT
503 ERRNO_CASE(ETIMEDOUT);
504#endif
505
506#ifdef ETXTBSY
507 ERRNO_CASE(ETXTBSY);
508#endif
509
510#ifdef EXDEV
511 ERRNO_CASE(EXDEV);
512#endif
513
514 default: return "";
515 }
516}
517
Felix Geisendörferf8a3cf92010-04-28 13:04:08518const char *signo_string(int signo) {
519#define SIGNO_CASE(e) case e: return #e;
520 switch (signo) {
Felix Geisendörferf8a3cf92010-04-28 13:04:08521#ifdef SIGHUP
522 SIGNO_CASE(SIGHUP);
523#endif
524
525#ifdef SIGINT
526 SIGNO_CASE(SIGINT);
527#endif
528
529#ifdef SIGQUIT
530 SIGNO_CASE(SIGQUIT);
531#endif
532
533#ifdef SIGILL
534 SIGNO_CASE(SIGILL);
535#endif
536
537#ifdef SIGTRAP
538 SIGNO_CASE(SIGTRAP);
539#endif
540
541#ifdef SIGABRT
542 SIGNO_CASE(SIGABRT);
543#endif
544
545#ifdef SIGIOT
546# if SIGABRT != SIGIOT
547 SIGNO_CASE(SIGIOT);
548# endif
549#endif
550
551#ifdef SIGBUS
552 SIGNO_CASE(SIGBUS);
553#endif
554
555#ifdef SIGFPE
556 SIGNO_CASE(SIGFPE);
557#endif
558
559#ifdef SIGKILL
560 SIGNO_CASE(SIGKILL);
561#endif
562
563#ifdef SIGUSR1
564 SIGNO_CASE(SIGUSR1);
565#endif
566
567#ifdef SIGSEGV
568 SIGNO_CASE(SIGSEGV);
569#endif
570
571#ifdef SIGUSR2
572 SIGNO_CASE(SIGUSR2);
573#endif
574
575#ifdef SIGPIPE
576 SIGNO_CASE(SIGPIPE);
577#endif
578
579#ifdef SIGALRM
580 SIGNO_CASE(SIGALRM);
581#endif
582
583 SIGNO_CASE(SIGTERM);
Bert Belderdcc35082010-11-25 00:04:31584
585#ifdef SIGCHLD
Felix Geisendörferf8a3cf92010-04-28 13:04:08586 SIGNO_CASE(SIGCHLD);
Bert Belderdcc35082010-11-25 00:04:31587#endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08588
589#ifdef SIGSTKFLT
590 SIGNO_CASE(SIGSTKFLT);
591#endif
592
593
594#ifdef SIGCONT
595 SIGNO_CASE(SIGCONT);
596#endif
597
598#ifdef SIGSTOP
599 SIGNO_CASE(SIGSTOP);
600#endif
601
602#ifdef SIGTSTP
603 SIGNO_CASE(SIGTSTP);
604#endif
605
Bert Belder600a6462012-08-20 21:59:21606#ifdef SIGBREAK
607 SIGNO_CASE(SIGBREAK);
608#endif
609
Felix Geisendörferf8a3cf92010-04-28 13:04:08610#ifdef SIGTTIN
611 SIGNO_CASE(SIGTTIN);
612#endif
613
614#ifdef SIGTTOU
615 SIGNO_CASE(SIGTTOU);
616#endif
617
618#ifdef SIGURG
619 SIGNO_CASE(SIGURG);
620#endif
621
622#ifdef SIGXCPU
623 SIGNO_CASE(SIGXCPU);
624#endif
625
626#ifdef SIGXFSZ
627 SIGNO_CASE(SIGXFSZ);
628#endif
629
630#ifdef SIGVTALRM
631 SIGNO_CASE(SIGVTALRM);
632#endif
633
634#ifdef SIGPROF
635 SIGNO_CASE(SIGPROF);
636#endif
637
638#ifdef SIGWINCH
639 SIGNO_CASE(SIGWINCH);
640#endif
641
642#ifdef SIGIO
643 SIGNO_CASE(SIGIO);
644#endif
645
646#ifdef SIGPOLL
Ryan Dahl3bb21b52010-04-28 22:07:15647# if SIGPOLL != SIGIO
Felix Geisendörferf8a3cf92010-04-28 13:04:08648 SIGNO_CASE(SIGPOLL);
Ryan Dahl3bb21b52010-04-28 22:07:15649# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08650#endif
651
652#ifdef SIGLOST
653 SIGNO_CASE(SIGLOST);
654#endif
655
656#ifdef SIGPWR
Raffaele Senab3b81d62010-06-09 04:08:05657# if SIGPWR != SIGLOST
Felix Geisendörferf8a3cf92010-04-28 13:04:08658 SIGNO_CASE(SIGPWR);
Raffaele Senab3b81d62010-06-09 04:08:05659# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08660#endif
661
662#ifdef SIGSYS
663 SIGNO_CASE(SIGSYS);
664#endif
665
Felix Geisendörferf8a3cf92010-04-28 13:04:08666 default: return "";
667 }
668}
669
Ryan Dahlc9e27b12010-04-23 00:53:45670
Fedor Indutny7b9771f2014-03-17 20:46:40671// Convenience methods
672
673
674void ThrowError(v8::Isolate* isolate, const char* errmsg) {
675 Environment::GetCurrent(isolate)->ThrowError(errmsg);
676}
677
678
679void ThrowTypeError(v8::Isolate* isolate, const char* errmsg) {
680 Environment::GetCurrent(isolate)->ThrowTypeError(errmsg);
681}
682
683
684void ThrowRangeError(v8::Isolate* isolate, const char* errmsg) {
685 Environment::GetCurrent(isolate)->ThrowRangeError(errmsg);
686}
687
688
689void ThrowErrnoException(v8::Isolate* isolate,
690 int errorno,
691 const char* syscall,
692 const char* message,
693 const char* path) {
694 Environment::GetCurrent(isolate)->ThrowErrnoException(errorno,
695 syscall,
696 message,
697 path);
698}
699
700
701void ThrowUVException(v8::Isolate* isolate,
702 int errorno,
703 const char* syscall,
704 const char* message,
Bert Belderbc2c85c2015-01-31 10:48:34705 const char* path,
706 const char* dest) {
707 Environment::GetCurrent(isolate)
708 ->ThrowUVException(errorno, syscall, message, path, dest);
Fedor Indutny7b9771f2014-03-17 20:46:40709}
710
711
Fedor Indutny75adde02014-02-21 13:02:42712Local<Value> ErrnoException(Isolate* isolate,
713 int errorno,
Ryan Dahlc9e27b12010-04-23 00:53:45714 const char *syscall,
visionmedia45948e02010-05-14 14:52:49715 const char *msg,
716 const char *path) {
Fedor Indutny75adde02014-02-21 13:02:42717 Environment* env = Environment::GetCurrent(isolate);
Ben Noordhuis756b6222013-08-10 22:26:11718
visionmedia45948e02010-05-14 14:52:49719 Local<Value> e;
Fedor Indutny75adde02014-02-21 13:02:42720 Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
Ben Noordhuis2d82cdf2014-10-22 01:29:32721 if (msg == nullptr || msg[0] == '\0') {
Bert Belder2ce09612011-01-17 21:47:59722 msg = strerror(errorno);
Bert Belder2ce09612011-01-17 21:47:59723 }
Fedor Indutny75adde02014-02-21 13:02:42724 Local<String> message = OneByteString(env->isolate(), msg);
Ryan Dahlc9e27b12010-04-23 00:53:45725
Ben Noordhuisf674b092013-08-07 19:50:41726 Local<String> cons1 =
Fedor Indutny75adde02014-02-21 13:02:42727 String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
Ryan Dahlc9e27b12010-04-23 00:53:45728 Local<String> cons2 = String::Concat(cons1, message);
729
visionmedia45948e02010-05-14 14:52:49730 if (path) {
Ben Noordhuisf674b092013-08-07 19:50:41731 Local<String> cons3 =
Fedor Indutny75adde02014-02-21 13:02:42732 String::Concat(cons2, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
Ben Noordhuisf674b092013-08-07 19:50:41733 Local<String> cons4 =
Fedor Indutny75adde02014-02-21 13:02:42734 String::Concat(cons3, String::NewFromUtf8(env->isolate(), path));
Ben Noordhuisf674b092013-08-07 19:50:41735 Local<String> cons5 =
Fedor Indutny75adde02014-02-21 13:02:42736 String::Concat(cons4, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
visionmedia45948e02010-05-14 14:52:49737 e = Exception::Error(cons5);
738 } else {
739 e = Exception::Error(cons2);
740 }
741
Trevor Norrisd5533862015-01-07 21:29:58742 Local<Object> obj = e->ToObject(env->isolate());
Fedor Indutnyce04c722014-03-13 16:38:14743 obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
Ben Noordhuis756b6222013-08-10 22:26:11744 obj->Set(env->code_string(), estring);
visionmedia45948e02010-05-14 14:52:49745
Ben Noordhuis2d82cdf2014-10-22 01:29:32746 if (path != nullptr) {
Fedor Indutny75adde02014-02-21 13:02:42747 obj->Set(env->path_string(), String::NewFromUtf8(env->isolate(), path));
Ben Noordhuis756b6222013-08-10 22:26:11748 }
749
Ben Noordhuis2d82cdf2014-10-22 01:29:32750 if (syscall != nullptr) {
Fedor Indutny75adde02014-02-21 13:02:42751 obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
Ben Noordhuis756b6222013-08-10 22:26:11752 }
753
Ryan Dahlc9e27b12010-04-23 00:53:45754 return e;
755}
756
757
Bert Belderbc2c85c2015-01-31 10:48:34758static Local<String> StringFromPath(Isolate* isolate, const char* path) {
759#ifdef _WIN32
760 if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
761 return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
762 String::NewFromUtf8(isolate, path + 8));
763 } else if (strncmp(path, "\\\\?\\", 4) == 0) {
764 return String::NewFromUtf8(isolate, path + 4);
765 }
766#endif
767
768 return String::NewFromUtf8(isolate, path);
769}
770
771
Fedor Indutny75adde02014-02-21 13:02:42772Local<Value> UVException(Isolate* isolate,
773 int errorno,
Bert Belderbc2c85c2015-01-31 10:48:34774 const char* syscall,
775 const char* msg,
776 const char* path) {
777 return UVException(isolate, errorno, syscall, msg, path, nullptr);
778}
779
780
781Local<Value> UVException(Isolate* isolate,
782 int errorno,
783 const char* syscall,
784 const char* msg,
785 const char* path,
786 const char* dest) {
Fedor Indutny75adde02014-02-21 13:02:42787 Environment* env = Environment::GetCurrent(isolate);
Bert Belder823a4432011-12-01 23:02:51788
789 if (!msg || !msg[0])
Ben Noordhuisca9eb712013-07-18 21:18:50790 msg = uv_strerror(errorno);
Bert Belder823a4432011-12-01 23:02:51791
Bert Belderbc2c85c2015-01-31 10:48:34792 Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
793 Local<String> js_syscall = OneByteString(isolate, syscall);
794 Local<String> js_path;
795 Local<String> js_dest;
Bert Belder823a4432011-12-01 23:02:51796
Bert Belderbc2c85c2015-01-31 10:48:34797 Local<String> js_msg = js_code;
798 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
799 js_msg = String::Concat(js_msg, OneByteString(isolate, msg));
800 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
801 js_msg = String::Concat(js_msg, js_syscall);
Ben Noordhuis756b6222013-08-10 22:26:11802
Ben Noordhuis2d82cdf2014-10-22 01:29:32803 if (path != nullptr) {
Bert Belderbc2c85c2015-01-31 10:48:34804 js_path = StringFromPath(isolate, path);
805
806 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
807 js_msg = String::Concat(js_msg, js_path);
808 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
Ben Noordhuis756b6222013-08-10 22:26:11809 }
810
Bert Belderbc2c85c2015-01-31 10:48:34811 if (dest != nullptr) {
812 js_dest = StringFromPath(isolate, dest);
813
814 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
815 js_msg = String::Concat(js_msg, js_dest);
816 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
Ben Noordhuis756b6222013-08-10 22:26:11817 }
818
Bert Belderbc2c85c2015-01-31 10:48:34819 Local<Object> e = Exception::Error(js_msg)->ToObject(isolate);
820
821 // TODO(piscisaureus) errno should probably go; the user has no way of
822 // knowing which uv errno value maps to which error.
823 e->Set(env->errno_string(), Integer::New(isolate, errorno));
824 e->Set(env->code_string(), js_code);
825 e->Set(env->syscall_string(), js_syscall);
826 if (!js_path.IsEmpty())
827 e->Set(env->path_string(), js_path);
828 if (!js_dest.IsEmpty())
829 e->Set(env->dest_string(), js_dest);
830
Bert Belder823a4432011-12-01 23:02:51831 return e;
832}
833
834
Ben Noordhuis8f6c5872014-10-11 19:48:25835// Look up environment variable unless running as setuid root.
836inline const char* secure_getenv(const char* key) {
837#ifndef _WIN32
838 if (getuid() != geteuid() || getgid() != getegid())
Ben Noordhuis2d82cdf2014-10-22 01:29:32839 return nullptr;
Ben Noordhuis8f6c5872014-10-11 19:48:25840#endif
841 return getenv(key);
842}
843
844
Bert Belder6ee73a22011-11-04 15:10:48845#ifdef _WIN32
Igor Zinkovsky500c8f42011-12-15 20:36:05846// Does about the same as strerror(),
847// but supports all windows error messages
Alexis Campailla93f3b642014-08-05 13:33:16848static const char *winapi_strerror(const int errorno, bool* must_free) {
Ben Noordhuis2d82cdf2014-10-22 01:29:32849 char *errmsg = nullptr;
Igor Zinkovsky500c8f42011-12-15 20:36:05850
851 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
Ben Noordhuis2d82cdf2014-10-22 01:29:32852 FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
853 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
Igor Zinkovsky500c8f42011-12-15 20:36:05854
855 if (errmsg) {
Alexis Campailla93f3b642014-08-05 13:33:16856 *must_free = true;
857
Igor Zinkovsky500c8f42011-12-15 20:36:05858 // Remove trailing newlines
859 for (int i = strlen(errmsg) - 1;
860 i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
861 errmsg[i] = '\0';
862 }
863
864 return errmsg;
865 } else {
866 // FormatMessage failed
Alexis Campailla93f3b642014-08-05 13:33:16867 *must_free = false;
Igor Zinkovsky500c8f42011-12-15 20:36:05868 return "Unknown error";
869 }
870}
871
872
Alexis Campailla440b9e22014-02-24 18:55:27873Local<Value> WinapiErrnoException(Isolate* isolate,
Fedor Indutny75adde02014-02-21 13:02:42874 int errorno,
Bert Belder829735e2011-11-04 15:23:02875 const char* syscall,
876 const char* msg,
877 const char* path) {
Alexis Campailla440b9e22014-02-24 18:55:27878 Environment* env = Environment::GetCurrent(isolate);
Bert Belder6ee73a22011-11-04 15:10:48879 Local<Value> e;
Alexis Campailla93f3b642014-08-05 13:33:16880 bool must_free = false;
Bert Belder829735e2011-11-04 15:23:02881 if (!msg || !msg[0]) {
Alexis Campailla93f3b642014-08-05 13:33:16882 msg = winapi_strerror(errorno, &must_free);
Bert Belder6ee73a22011-11-04 15:10:48883 }
Fedor Indutny75adde02014-02-21 13:02:42884 Local<String> message = OneByteString(env->isolate(), msg);
Bert Belder6ee73a22011-11-04 15:10:48885
Bert Belder6ee73a22011-11-04 15:10:48886 if (path) {
Ben Noordhuisf674b092013-08-07 19:50:41887 Local<String> cons1 =
Alexis Campailla440b9e22014-02-24 18:55:27888 String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
Ben Noordhuisf674b092013-08-07 19:50:41889 Local<String> cons2 =
Alexis Campailla440b9e22014-02-24 18:55:27890 String::Concat(cons1, String::NewFromUtf8(isolate, path));
Ben Noordhuisf674b092013-08-07 19:50:41891 Local<String> cons3 =
Alexis Campailla440b9e22014-02-24 18:55:27892 String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
Bert Belder6ee73a22011-11-04 15:10:48893 e = Exception::Error(cons3);
894 } else {
895 e = Exception::Error(message);
896 }
897
Trevor Norrisd5533862015-01-07 21:29:58898 Local<Object> obj = e->ToObject(env->isolate());
Fedor Indutnyce04c722014-03-13 16:38:14899 obj->Set(env->errno_string(), Integer::New(isolate, errorno));
Bert Belder6ee73a22011-11-04 15:10:48900
Ben Noordhuis2d82cdf2014-10-22 01:29:32901 if (path != nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:27902 obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
Ben Noordhuis756b6222013-08-10 22:26:11903 }
904
Ben Noordhuis2d82cdf2014-10-22 01:29:32905 if (syscall != nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:27906 obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
Ben Noordhuis756b6222013-08-10 22:26:11907 }
908
Alexis Campailla93f3b642014-08-05 13:33:16909 if (must_free)
910 LocalFree((HLOCAL)msg);
911
Bert Belder6ee73a22011-11-04 15:10:48912 return e;
913}
914#endif
915
916
Trevor Norris828f1452014-01-09 19:11:40917void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:55918 Environment* env = Environment::GetCurrent(args);
Trevor Norris828f1452014-01-09 19:11:40919
920 if (env->using_domains())
921 return;
922 env->set_using_domains(true);
923
Fedor Indutny75adde02014-02-21 13:02:42924 HandleScope scope(env->isolate());
Trevor Norris828f1452014-01-09 19:11:40925 Local<Object> process_object = env->process_object();
926
Fedor Indutny75adde02014-02-21 13:02:42927 Local<String> tick_callback_function_key = env->tick_domain_cb_string();
Trevor Norris828f1452014-01-09 19:11:40928 Local<Function> tick_callback_function =
929 process_object->Get(tick_callback_function_key).As<Function>();
930
931 if (!tick_callback_function->IsFunction()) {
932 fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
933 abort();
934 }
935
Fedor Indutny75adde02014-02-21 13:02:42936 process_object->Set(env->tick_callback_string(), tick_callback_function);
Trevor Norris828f1452014-01-09 19:11:40937 env->set_tick_callback_function(tick_callback_function);
938
Ben Noordhuis5fdff382014-10-11 14:52:07939 CHECK(args[0]->IsArray());
940 CHECK(args[1]->IsObject());
Trevor Norris828f1452014-01-09 19:11:40941
942 env->set_domain_array(args[0].As<Array>());
943
944 Local<Object> domain_flag_obj = args[1].As<Object>();
945 Environment::DomainFlag* domain_flag = env->domain_flag();
946 domain_flag_obj->SetIndexedPropertiesToExternalArrayData(
947 domain_flag->fields(),
Trevor Norrisbdc2ea42014-10-08 08:34:46948 kExternalUint32Array,
Trevor Norris828f1452014-01-09 19:11:40949 domain_flag->fields_count());
950
951 // Do a little housekeeping.
952 env->process_object()->Delete(
953 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse"));
954}
955
Vladimir Kurchatkin30bd7b62014-09-04 16:02:04956void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
957 args.GetIsolate()->RunMicrotasks();
958}
959
Trevor Norris828f1452014-01-09 19:11:40960
Trevor Norrisefa62fd2013-09-24 21:12:11961void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:55962 Environment* env = Environment::GetCurrent(args);
Trevor Norrisefa62fd2013-09-24 21:12:11963
Ben Noordhuis5fdff382014-10-11 14:52:07964 CHECK(args[0]->IsObject());
965 CHECK(args[1]->IsFunction());
966 CHECK(args[2]->IsObject());
Trevor Norrisefa62fd2013-09-24 21:12:11967
968 // Values use to cross communicate with processNextTick.
969 Local<Object> tick_info_obj = args[0].As<Object>();
970 tick_info_obj->SetIndexedPropertiesToExternalArrayData(
971 env->tick_info()->fields(),
Trevor Norrisbdc2ea42014-10-08 08:34:46972 kExternalUint32Array,
Trevor Norrisefa62fd2013-09-24 21:12:11973 env->tick_info()->fields_count());
974
975 env->set_tick_callback_function(args[1].As<Function>());
976
Ben Noordhuisd3c317e2014-10-13 13:19:55977 env->SetMethod(args[2].As<Object>(), "runMicrotasks", RunMicrotasks);
Vladimir Kurchatkin30bd7b62014-09-04 16:02:04978
Trevor Norrisefa62fd2013-09-24 21:12:11979 // Do a little housekeeping.
980 env->process_object()->Delete(
981 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick"));
Trevor Norris3f5d5842013-08-07 00:01:44982}
983
984
Ben Noordhuis756b6222013-08-10 22:26:11985Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:16986 Handle<Value> recv,
Ben Noordhuis756b6222013-08-10 22:26:11987 const Handle<Function> callback,
988 int argc,
989 Handle<Value> argv[]) {
Trevor Norrisefa62fd2013-09-24 21:12:11990 // If you hit this assertion, you forgot to enter the v8::Context first.
Ben Noordhuis5fdff382014-10-11 14:52:07991 CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
Trevor Norrisefa62fd2013-09-24 21:12:11992
993 Local<Object> process = env->process_object();
Trevor Norrisa1da0242014-12-09 04:24:59994 Local<Object> object, domain;
Trevor Norrisb9e60322014-12-09 04:10:44995 bool has_async_queue = false;
Trevor Norrisa1da0242014-12-09 04:24:59996 bool has_domain = false;
997
Trevor Norrisb9e60322014-12-09 04:10:44998 if (recv->IsObject()) {
999 object = recv.As<Object>();
1000 Local<Value> async_queue_v = object->Get(env->async_queue_string());
1001 if (async_queue_v->IsObject())
1002 has_async_queue = true;
1003 }
1004
Trevor Norrisa1da0242014-12-09 04:24:591005 if (env->using_domains()) {
1006 CHECK(recv->IsObject());
Trevor Norrisa1da0242014-12-09 04:24:591007 Local<Value> domain_v = object->Get(env->domain_string());
1008 has_domain = domain_v->IsObject();
1009 if (has_domain) {
1010 domain = domain_v.As<Object>();
1011 if (domain->Get(env->disposed_string())->IsTrue())
1012 return Undefined(env->isolate());
1013 }
1014 }
Trevor Norrisefa62fd2013-09-24 21:12:111015
Trevor Norris86c07452013-02-07 01:26:181016 TryCatch try_catch;
Miroslav Bajtosc16963b2013-06-17 19:19:591017 try_catch.SetVerbose(true);
Trevor Norris86c07452013-02-07 01:26:181018
Trevor Norrisa1da0242014-12-09 04:24:591019 if (has_domain) {
1020 Local<Value> enter_v = domain->Get(env->enter_string());
1021 if (enter_v->IsFunction()) {
1022 enter_v.As<Function>()->Call(domain, 0, nullptr);
1023 if (try_catch.HasCaught())
1024 return Undefined(env->isolate());
1025 }
1026 }
1027
Trevor Norrisb9e60322014-12-09 04:10:441028 if (has_async_queue) {
1029 try_catch.SetVerbose(false);
1030 env->async_hooks_pre_function()->Call(object, 0, nullptr);
1031 if (try_catch.HasCaught())
1032 FatalError("node:;MakeCallback", "pre hook threw");
1033 try_catch.SetVerbose(true);
1034 }
1035
Ben Noordhuis1f2f3fa2014-01-27 02:58:161036 Local<Value> ret = callback->Call(recv, argc, argv);
isaacs10ce3d12012-04-13 23:27:231037
Trevor Norrisb9e60322014-12-09 04:10:441038 if (has_async_queue) {
1039 try_catch.SetVerbose(false);
1040 env->async_hooks_post_function()->Call(object, 0, nullptr);
1041 if (try_catch.HasCaught())
1042 FatalError("node::MakeCallback", "post hook threw");
1043 try_catch.SetVerbose(true);
1044 }
1045
Trevor Norrisa1da0242014-12-09 04:24:591046 if (has_domain) {
1047 Local<Value> exit_v = domain->Get(env->exit_string());
1048 if (exit_v->IsFunction()) {
1049 exit_v.As<Function>()->Call(domain, 0, nullptr);
1050 if (try_catch.HasCaught())
1051 return Undefined(env->isolate());
1052 }
1053 }
1054 env->tick_callback_function()->Call(process, 0, nullptr);
1055 CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
1056
isaacs10ce3d12012-04-13 23:27:231057 if (try_catch.HasCaught()) {
Fedor Indutny75adde02014-02-21 13:02:421058 return Undefined(env->isolate());
Ryan Dahl650a3082011-05-28 20:44:031059 }
isaacsac1aadd2012-04-13 23:34:481060
Ben Noordhuis756b6222013-08-10 22:26:111061 Environment::TickInfo* tick_info = env->tick_info();
1062
Trevor Norrisefa62fd2013-09-24 21:12:111063 if (tick_info->in_tick()) {
Trevor Norris6a5a7b02013-07-30 22:06:451064 return ret;
1065 }
1066
Ben Noordhuis756b6222013-08-10 22:26:111067 if (tick_info->length() == 0) {
Vladimir Kurchatkin8dc6be12014-09-22 16:19:501068 env->isolate()->RunMicrotasks();
1069 }
1070
1071 if (tick_info->length() == 0) {
Ben Noordhuis756b6222013-08-10 22:26:111072 tick_info->set_index(0);
Trevor Norrisa0867e12013-03-17 04:59:471073 return ret;
Trevor Norrisec420002013-02-13 14:30:061074 }
1075
Trevor Norris4b84e422013-08-27 18:30:061076 tick_info->set_in_tick(true);
1077
Trevor Norris86c07452013-02-07 01:26:181078 // process nextTicks after call
Ben Noordhuis2d82cdf2014-10-22 01:29:321079 env->tick_callback_function()->Call(process, 0, nullptr);
Trevor Norris86c07452013-02-07 01:26:181080
Trevor Norris4b84e422013-08-27 18:30:061081 tick_info->set_in_tick(false);
1082
Trevor Norris86c07452013-02-07 01:26:181083 if (try_catch.HasCaught()) {
Trevor Norris4b84e422013-08-27 18:30:061084 tick_info->set_last_threw(true);
Fedor Indutny75adde02014-02-21 13:02:421085 return Undefined(env->isolate());
Trevor Norris86c07452013-02-07 01:26:181086 }
1087
Trevor Norrisa0867e12013-03-17 04:59:471088 return ret;
1089}
1090
1091
Ben Noordhuis7a3f7782013-08-15 17:22:441092// Internal only.
Ben Noordhuis756b6222013-08-10 22:26:111093Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161094 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111095 uint32_t index,
1096 int argc,
1097 Handle<Value> argv[]) {
Trevor Norrisa1da0242014-12-09 04:24:591098 Local<Value> cb_v = recv->Get(index);
1099 CHECK(cb_v->IsFunction());
1100 return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
Ben Noordhuis7a3f7782013-08-15 17:22:441101}
1102
1103
Ben Noordhuis756b6222013-08-10 22:26:111104Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161105 Handle<Object> recv,
1106 Handle<String> symbol,
Ben Noordhuis756b6222013-08-10 22:26:111107 int argc,
1108 Handle<Value> argv[]) {
Trevor Norrisa1da0242014-12-09 04:24:591109 Local<Value> cb_v = recv->Get(symbol);
1110 CHECK(cb_v->IsFunction());
1111 return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
Trevor Norris86c07452013-02-07 01:26:181112}
1113
1114
Ben Noordhuis756b6222013-08-10 22:26:111115Handle<Value> MakeCallback(Environment* env,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161116 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111117 const char* method,
1118 int argc,
1119 Handle<Value> argv[]) {
Fedor Indutny75adde02014-02-21 13:02:421120 Local<String> method_string = OneByteString(env->isolate(), method);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161121 return MakeCallback(env, recv, method_string, argc, argv);
Ben Noordhuis756b6222013-08-10 22:26:111122}
Trevor Norris86c07452013-02-07 01:26:181123
Ben Noordhuis756b6222013-08-10 22:26:111124
Fedor Indutny75adde02014-02-21 13:02:421125Handle<Value> MakeCallback(Isolate* isolate,
1126 Handle<Object> recv,
Ben Noordhuis756b6222013-08-10 22:26:111127 const char* method,
1128 int argc,
1129 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141130 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161131 Local<Context> context = recv->CreationContext();
Ben Noordhuis756b6222013-08-10 22:26:111132 Environment* env = Environment::GetCurrent(context);
1133 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141134 return handle_scope.Escape(
1135 Local<Value>::New(isolate, MakeCallback(env, recv, method, argc, argv)));
Ben Noordhuis756b6222013-08-10 22:26:111136}
1137
1138
Fedor Indutny75adde02014-02-21 13:02:421139Handle<Value> MakeCallback(Isolate* isolate,
1140 Handle<Object> recv,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161141 Handle<String> symbol,
Ben Noordhuis756b6222013-08-10 22:26:111142 int argc,
1143 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141144 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161145 Local<Context> context = recv->CreationContext();
Ben Noordhuis756b6222013-08-10 22:26:111146 Environment* env = Environment::GetCurrent(context);
1147 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141148 return handle_scope.Escape(
1149 Local<Value>::New(isolate, MakeCallback(env, recv, symbol, argc, argv)));
Ben Noordhuis756b6222013-08-10 22:26:111150}
1151
1152
Fedor Indutny75adde02014-02-21 13:02:421153Handle<Value> MakeCallback(Isolate* isolate,
1154 Handle<Object> recv,
Ben Noordhuis1f2f3fa2014-01-27 02:58:161155 Handle<Function> callback,
Ben Noordhuis756b6222013-08-10 22:26:111156 int argc,
1157 Handle<Value> argv[]) {
Fedor Indutnyce04c722014-03-13 16:38:141158 EscapableHandleScope handle_scope(isolate);
Ben Noordhuis1f2f3fa2014-01-27 02:58:161159 Local<Context> context = recv->CreationContext();
Trevor Norris828f1452014-01-09 19:11:401160 Environment* env = Environment::GetCurrent(context);
1161 Context::Scope context_scope(context);
Fedor Indutnyce04c722014-03-13 16:38:141162 return handle_scope.Escape(Local<Value>::New(
1163 isolate,
1164 MakeCallback(env, recv.As<Value>(), callback, argc, argv)));
Ben Noordhuis1f2f3fa2014-01-27 02:58:161165}
1166
1167
Fedor Indutnyc6367e72015-01-30 12:05:281168enum encoding ParseEncoding(const char* encoding,
1169 enum encoding default_encoding) {
1170 switch (encoding[0]) {
1171 case 'u':
1172 // utf8, utf16le
1173 if (encoding[1] == 't' && encoding[2] == 'f') {
1174 // Skip `-`
1175 encoding += encoding[3] == '-' ? 4 : 3;
1176 if (encoding[0] == '8' && encoding[1] == '\0')
1177 return UTF8;
1178 if (strncmp(encoding, "16le", 4) == 0)
1179 return UCS2;
Ryan Dahl07792af2009-09-21 10:27:221180
Fedor Indutnyc6367e72015-01-30 12:05:281181 // ucs2
1182 } else if (encoding[1] == 'c' && encoding[2] == 's') {
1183 encoding += encoding[3] == '-' ? 4 : 3;
1184 if (encoding[0] == '2' && encoding[1] == '\0')
1185 return UCS2;
1186 }
1187 break;
1188 case 'b':
1189 // binary
1190 if (encoding[1] == 'i') {
1191 if (strncmp(encoding + 2, "nary", 4) == 0)
1192 return BINARY;
Ryan Dahl07792af2009-09-21 10:27:221193
Fedor Indutnyc6367e72015-01-30 12:05:281194 // buffer
1195 } else if (encoding[1] == 'u') {
1196 if (strncmp(encoding + 2, "ffer", 4) == 0)
1197 return BUFFER;
1198 }
1199 break;
1200 case '\0':
1201 return default_encoding;
1202 default:
1203 break;
1204 }
Ryan Dahl07792af2009-09-21 10:27:221205
Fedor Indutnyc6367e72015-01-30 12:05:281206 if (strcasecmp(encoding, "utf8") == 0) {
Ryan Dahl07792af2009-09-21 10:27:221207 return UTF8;
Fedor Indutnyc6367e72015-01-30 12:05:281208 } else if (strcasecmp(encoding, "utf-8") == 0) {
Ryan Dahl2b994d92009-10-06 08:45:181209 return UTF8;
Fedor Indutnyc6367e72015-01-30 12:05:281210 } else if (strcasecmp(encoding, "ascii") == 0) {
Ryan Dahl07792af2009-09-21 10:27:221211 return ASCII;
Fedor Indutnyc6367e72015-01-30 12:05:281212 } else if (strcasecmp(encoding, "base64") == 0) {
Ben Noordhuis95638c92010-07-28 12:20:231213 return BASE64;
Fedor Indutnyc6367e72015-01-30 12:05:281214 } else if (strcasecmp(encoding, "ucs2") == 0) {
Konstantin Käfer9e101f22011-02-06 20:49:521215 return UCS2;
Fedor Indutnyc6367e72015-01-30 12:05:281216 } else if (strcasecmp(encoding, "ucs-2") == 0) {
Konstantin Käfer9e101f22011-02-06 20:49:521217 return UCS2;
Fedor Indutnyc6367e72015-01-30 12:05:281218 } else if (strcasecmp(encoding, "utf16le") == 0) {
koichikfbb0ee62012-10-02 14:57:381219 return UCS2;
Fedor Indutnyc6367e72015-01-30 12:05:281220 } else if (strcasecmp(encoding, "utf-16le") == 0) {
koichikfbb0ee62012-10-02 14:57:381221 return UCS2;
Fedor Indutnyc6367e72015-01-30 12:05:281222 } else if (strcasecmp(encoding, "binary") == 0) {
Ryan Dahl07792af2009-09-21 10:27:221223 return BINARY;
Fedor Indutnyc6367e72015-01-30 12:05:281224 } else if (strcasecmp(encoding, "buffer") == 0) {
Fedor Indutny63ff4492012-09-12 20:35:591225 return BUFFER;
Fedor Indutnyc6367e72015-01-30 12:05:281226 } else if (strcasecmp(encoding, "hex") == 0) {
isaacs0aa1a8a2011-02-20 01:29:011227 return HEX;
Fedor Indutnyc6367e72015-01-30 12:05:281228 } else if (strcasecmp(encoding, "raw") == 0) {
isaacs5b399292012-06-21 18:42:331229 if (!no_deprecation) {
1230 fprintf(stderr, "'raw' (array of integers) has been removed. "
1231 "Use 'binary'.\n");
1232 }
Ryan Dahl07792af2009-09-21 10:27:221233 return BINARY;
Fedor Indutnyc6367e72015-01-30 12:05:281234 } else if (strcasecmp(encoding, "raws") == 0) {
isaacs5b399292012-06-21 18:42:331235 if (!no_deprecation) {
1236 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1237 "Please update your code.\n");
1238 }
Ryan Dahl07792af2009-09-21 10:27:221239 return BINARY;
1240 } else {
Fedor Indutnyc6367e72015-01-30 12:05:281241 return default_encoding;
Ryan Dahl07792af2009-09-21 10:27:221242 }
1243}
1244
Fedor Indutnyc6367e72015-01-30 12:05:281245
1246enum encoding ParseEncoding(Isolate* isolate,
1247 Handle<Value> encoding_v,
1248 enum encoding default_encoding) {
1249 if (!encoding_v->IsString())
1250 return default_encoding;
1251
1252 node::Utf8Value encoding(isolate, encoding_v);
1253
1254 return ParseEncoding(*encoding, default_encoding);
1255}
1256
Fedor Indutny75adde02014-02-21 13:02:421257Local<Value> Encode(Isolate* isolate,
Ben Noordhuis56fde662014-12-10 16:33:561258 const char* buf,
Fedor Indutny75adde02014-02-21 13:02:421259 size_t len,
1260 enum encoding encoding) {
Ben Noordhuis56fde662014-12-10 16:33:561261 CHECK_NE(encoding, UCS2);
1262 return StringBytes::Encode(isolate, buf, len, encoding);
1263}
1264
1265Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1266 return StringBytes::Encode(isolate, buf, len);
Ryan21a1b042009-09-09 13:51:491267}
1268
Ryand6c9d312009-09-11 14:02:291269// Returns -1 if the handle was not valid for decoding
Fedor Indutny75adde02014-02-21 13:02:421270ssize_t DecodeBytes(Isolate* isolate,
1271 Handle<Value> val,
1272 enum encoding encoding) {
1273 HandleScope scope(isolate);
Ryan21a1b042009-09-09 13:51:491274
1275 if (val->IsArray()) {
isaacsa3753b42012-05-16 23:32:371276 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1277 "Use 'binary'.\n");
Ben Noordhuis5fdff382014-10-11 14:52:071278 UNREACHABLE();
Ryan Dahl07792af2009-09-21 10:27:221279 return -1;
Ryan21a1b042009-09-09 13:51:491280 }
1281
Fedor Indutny75adde02014-02-21 13:02:421282 return StringBytes::Size(isolate, val, encoding);
Ryan21a1b042009-09-09 13:51:491283}
1284
Ryan21a1b042009-09-09 13:51:491285// Returns number of bytes written.
Fedor Indutny75adde02014-02-21 13:02:421286ssize_t DecodeWrite(Isolate* isolate,
1287 char* buf,
Ryan Dahl53530e92010-04-02 21:55:281288 size_t buflen,
Fedor Indutny75adde02014-02-21 13:02:421289 Handle<Value> val,
Ryand6c9d312009-09-11 14:02:291290 enum encoding encoding) {
Ben Noordhuis2d82cdf2014-10-22 01:29:321291 return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
Ryan21a1b042009-09-09 13:51:491292}
1293
Fedor Indutnyf1de13b2014-02-05 16:38:331294void AppendExceptionLine(Environment* env,
1295 Handle<Value> er,
1296 Handle<Message> message) {
1297 if (message.IsEmpty())
Fedor Indutny2bc30f22013-10-16 16:57:261298 return;
isaacsb3cf3f32012-07-28 21:00:271299
Fedor Indutnyf1de13b2014-02-05 16:38:331300 HandleScope scope(env->isolate());
1301 Local<Object> err_obj;
1302 if (!er.IsEmpty() && er->IsObject()) {
1303 err_obj = er.As<Object>();
Ryan Dahlcdf5d912011-10-11 20:41:331304
Fedor Indutnyf1de13b2014-02-05 16:38:331305 // Do it only once per message
1306 if (!err_obj->GetHiddenValue(env->processed_string()).IsEmpty())
1307 return;
1308 err_obj->SetHiddenValue(env->processed_string(), True(env->isolate()));
Ryan Dahl8e6dd522010-01-15 18:45:041309 }
Fedor Indutnyf1de13b2014-02-05 16:38:331310
Ben Noordhuis8ba39b02014-11-12 14:29:341311 char arrow[1024];
Fedor Indutnyf1de13b2014-02-05 16:38:331312
1313 // Print (filename):(line number): (message).
Trevor Norriscbf76c12015-01-07 22:13:351314 node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
Fedor Indutnyf1de13b2014-02-05 16:38:331315 const char* filename_string = *filename;
1316 int linenum = message->GetLineNumber();
1317 // Print line of source code.
Trevor Norriscbf76c12015-01-07 22:13:351318 node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
Fedor Indutnyf1de13b2014-02-05 16:38:331319 const char* sourceline_string = *sourceline;
1320
1321 // Because of how node modules work, all scripts are wrapped with a
1322 // "function (module, exports, __filename, ...) {"
1323 // to provide script local variables.
1324 //
1325 // When reporting errors on the first line of a script, this wrapper
1326 // function is leaked to the user. There used to be a hack here to
1327 // truncate off the first 62 characters, but it caused numerous other
1328 // problems when vm.runIn*Context() methods were used for non-module
1329 // code.
1330 //
1331 // If we ever decide to re-instate such a hack, the following steps
1332 // must be taken:
1333 //
1334 // 1. Pass a flag around to say "this code was wrapped"
1335 // 2. Update the stack frame output so that it is also correct.
1336 //
1337 // It would probably be simpler to add a line rather than add some
1338 // number of characters to the first line, since V8 truncates the
1339 // sourceline to 78 characters, and we end up not providing very much
1340 // useful debugging info to the user if we remove 62 characters.
1341
1342 int start = message->GetStartColumn();
1343 int end = message->GetEndColumn();
1344
1345 int off = snprintf(arrow,
1346 sizeof(arrow),
1347 "%s:%i\n%s\n",
1348 filename_string,
1349 linenum,
1350 sourceline_string);
Ben Noordhuis5fdff382014-10-11 14:52:071351 CHECK_GE(off, 0);
Fedor Indutnyf1de13b2014-02-05 16:38:331352
1353 // Print wavy underline (GetUnderline is deprecated).
1354 for (int i = 0; i < start; i++) {
Yazhong Liu6b09f9c2014-06-25 13:18:501355 if (sourceline_string[i] == '\0' ||
1356 static_cast<size_t>(off) >= sizeof(arrow)) {
1357 break;
1358 }
Ben Noordhuis5fdff382014-10-11 14:52:071359 CHECK_LT(static_cast<size_t>(off), sizeof(arrow));
Fedor Indutnyf1de13b2014-02-05 16:38:331360 arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1361 }
1362 for (int i = start; i < end; i++) {
Yazhong Liu6b09f9c2014-06-25 13:18:501363 if (sourceline_string[i] == '\0' ||
1364 static_cast<size_t>(off) >= sizeof(arrow)) {
1365 break;
1366 }
Ben Noordhuis5fdff382014-10-11 14:52:071367 CHECK_LT(static_cast<size_t>(off), sizeof(arrow));
Fedor Indutnyf1de13b2014-02-05 16:38:331368 arrow[off++] = '^';
1369 }
Ben Noordhuis5fdff382014-10-11 14:52:071370 CHECK_LE(static_cast<size_t>(off - 1), sizeof(arrow) - 1);
Fedor Indutnyf1de13b2014-02-05 16:38:331371 arrow[off++] = '\n';
1372 arrow[off] = '\0';
1373
1374 Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1375 Local<Value> msg;
1376 Local<Value> stack;
1377
1378 // Allocation failed, just print it out
1379 if (arrow_str.IsEmpty() || err_obj.IsEmpty() || !err_obj->IsNativeError())
1380 goto print;
1381
1382 msg = err_obj->Get(env->message_string());
1383 stack = err_obj->Get(env->stack_string());
1384
1385 if (msg.IsEmpty() || stack.IsEmpty())
1386 goto print;
1387
1388 err_obj->Set(env->message_string(),
Trevor Norrisd5533862015-01-07 21:29:581389 String::Concat(arrow_str, msg->ToString(env->isolate())));
Fedor Indutnyf1de13b2014-02-05 16:38:331390 err_obj->Set(env->stack_string(),
Trevor Norrisd5533862015-01-07 21:29:581391 String::Concat(arrow_str, stack->ToString(env->isolate())));
Fedor Indutnyf1de13b2014-02-05 16:38:331392 return;
1393
1394 print:
1395 if (env->printed_error())
1396 return;
1397 env->set_printed_error(true);
1398 uv_tty_reset_mode();
1399 fprintf(stderr, "\n%s", arrow);
Ryan Dahlb57c1f52010-11-24 02:46:131400}
1401
1402
Fedor Indutnyf1de13b2014-02-05 16:38:331403static void ReportException(Environment* env,
1404 Handle<Value> er,
1405 Handle<Message> message) {
1406 HandleScope scope(env->isolate());
Ryan Dahlb57c1f52010-11-24 02:46:131407
Fedor Indutnyf1de13b2014-02-05 16:38:331408 AppendExceptionLine(env, er, message);
Ryan Dahl53a841d2009-12-29 19:20:511409
Vladimir Kurchatkin259d4492013-12-06 11:56:371410 Local<Value> trace_value;
1411
Fedor Indutnyf1de13b2014-02-05 16:38:331412 if (er->IsUndefined() || er->IsNull())
1413 trace_value = Undefined(env->isolate());
1414 else
Trevor Norrisd5533862015-01-07 21:29:581415 trace_value = er->ToObject(env->isolate())->Get(env->stack_string());
Vladimir Kurchatkin259d4492013-12-06 11:56:371416
Trevor Norriscbf76c12015-01-07 22:13:351417 node::Utf8Value trace(env->isolate(), trace_value);
Ryan Dahlda932302010-05-14 18:48:141418
isaacs8df6f9e2011-04-25 19:22:181419 // range errors have a trace member set to undefined
Miroslav Bajtosc16963b2013-06-17 19:19:591420 if (trace.length() > 0 && !trace_value->IsUndefined()) {
Ryanafd9e712009-08-31 16:22:091421 fprintf(stderr, "%s\n", *trace);
isaacse9b6b0b2010-10-02 06:22:341422 } else {
1423 // this really only happens for RangeErrors, since they're the only
isaacs8df6f9e2011-04-25 19:22:181424 // kind that won't have all this info in the trace, or when non-Error
1425 // objects are thrown manually.
Ben Noordhuisf674b092013-08-07 19:50:411426 Local<Value> message;
1427 Local<Value> name;
isaacs8df6f9e2011-04-25 19:22:181428
Ben Noordhuisf674b092013-08-07 19:50:411429 if (er->IsObject()) {
1430 Local<Object> err_obj = er.As<Object>();
Fedor Indutnyf1de13b2014-02-05 16:38:331431 message = err_obj->Get(env->message_string());
1432 name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
isaacs8df6f9e2011-04-25 19:22:181433 }
1434
Ben Noordhuisf674b092013-08-07 19:50:411435 if (message.IsEmpty() ||
1436 message->IsUndefined() ||
1437 name.IsEmpty() ||
1438 name->IsUndefined()) {
1439 // Not an error object. Just print as-is.
Trevor Norriscbf76c12015-01-07 22:13:351440 node::Utf8Value message(env->isolate(), er);
Ben Noordhuisf674b092013-08-07 19:50:411441 fprintf(stderr, "%s\n", *message);
1442 } else {
Trevor Norriscbf76c12015-01-07 22:13:351443 node::Utf8Value name_string(env->isolate(), name);
1444 node::Utf8Value message_string(env->isolate(), message);
Ben Noordhuisf674b092013-08-07 19:50:411445 fprintf(stderr, "%s: %s\n", *name_string, *message_string);
1446 }
Ryan5131e0a2009-03-09 00:23:411447 }
isaacse9b6b0b2010-10-02 06:22:341448
Ryand7e220c2009-09-09 20:35:401449 fflush(stderr);
Ryan5131e0a2009-03-09 00:23:411450}
1451
Miroslav Bajtosc16963b2013-06-17 19:19:591452
Fedor Indutnyf1de13b2014-02-05 16:38:331453static void ReportException(Environment* env, const TryCatch& try_catch) {
1454 ReportException(env, try_catch.Exception(), try_catch.Message());
Miroslav Bajtosc16963b2013-06-17 19:19:591455}
1456
1457
Ryand6c9d312009-09-11 14:02:291458// Executes a str within the current v8 context.
Fedor Indutnyf1de13b2014-02-05 16:38:331459static Local<Value> ExecuteString(Environment* env,
1460 Handle<String> source,
Ben Noordhuisc7214fe2014-03-31 13:13:371461 Handle<String> filename) {
Fedor Indutnyce04c722014-03-13 16:38:141462 EscapableHandleScope scope(env->isolate());
Ryan408526a2009-04-21 11:52:211463 TryCatch try_catch;
1464
Miroslav Bajtosc16963b2013-06-17 19:19:591465 // try_catch must be nonverbose to disable FatalException() handler,
1466 // we will handle exceptions ourself.
1467 try_catch.SetVerbose(false);
1468
Herbert Vojcikc2a06722010-04-17 15:18:151469 Local<v8::Script> script = v8::Script::Compile(source, filename);
Ryan63a9cd32009-04-15 08:08:281470 if (script.IsEmpty()) {
Fedor Indutnyf1de13b2014-02-05 16:38:331471 ReportException(env, try_catch);
isaacs95862b22013-02-27 19:23:201472 exit(3);
Ryan63a9cd32009-04-15 08:08:281473 }
1474
Ryan Dahl9f5643f2010-01-31 07:22:341475 Local<Value> result = script->Run();
Ryan63a9cd32009-04-15 08:08:281476 if (result.IsEmpty()) {
Fedor Indutnyf1de13b2014-02-05 16:38:331477 ReportException(env, try_catch);
isaacs95862b22013-02-27 19:23:201478 exit(4);
Ryan63a9cd32009-04-15 08:08:281479 }
1480
Fedor Indutnyce04c722014-03-13 16:38:141481 return scope.Escape(result);
Ryan63a9cd32009-04-15 08:08:281482}
1483
Felix Geisendörfer7371fcb2009-11-11 17:10:581484
Ben Noordhuis110a9cd2013-07-03 02:23:441485static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551486 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis5f040652012-04-28 16:45:101487
Fedor Indutnyce04c722014-03-13 16:38:141488 Local<Array> ary = Array::New(args.GetIsolate());
Ben Noordhuis2d82cdf2014-10-22 01:29:321489 QUEUE* q = nullptr;
Ben Noordhuis5f040652012-04-28 16:45:101490 int i = 0;
1491
Fedor Indutny6a610a02014-10-04 14:44:391492 QUEUE_FOREACH(q, env->req_wrap_queue()) {
Ben Noordhuis820aaf52014-05-27 21:31:311493 ReqWrap<uv_req_t>* w = ContainerOf(&ReqWrap<uv_req_t>::req_wrap_queue_, q);
Fedor Indutny2bc30f22013-10-16 16:57:261494 if (w->persistent().IsEmpty())
1495 continue;
Ben Noordhuis110a9cd2013-07-03 02:23:441496 ary->Set(i++, w->object());
Ben Noordhuis5f040652012-04-28 16:45:101497 }
1498
Ben Noordhuis110a9cd2013-07-03 02:23:441499 args.GetReturnValue().Set(ary);
Ben Noordhuis5f040652012-04-28 16:45:101500}
1501
1502
1503// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1504// implemented here for consistency with GetActiveRequests().
Ben Noordhuis110a9cd2013-07-03 02:23:441505void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551506 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis5f040652012-04-28 16:45:101507
Fedor Indutnyce04c722014-03-13 16:38:141508 Local<Array> ary = Array::New(env->isolate());
Ben Noordhuis2d82cdf2014-10-22 01:29:321509 QUEUE* q = nullptr;
Ben Noordhuis5f040652012-04-28 16:45:101510 int i = 0;
1511
Fedor Indutny75adde02014-02-21 13:02:421512 Local<String> owner_sym = env->owner_string();
Ben Noordhuise813e342012-05-15 15:24:061513
Fedor Indutny6a610a02014-10-04 14:44:391514 QUEUE_FOREACH(q, env->handle_wrap_queue()) {
Ben Noordhuis820aaf52014-05-27 21:31:311515 HandleWrap* w = ContainerOf(&HandleWrap::handle_wrap_queue_, q);
Fedor Indutny2bc30f22013-10-16 16:57:261516 if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
1517 continue;
Ben Noordhuis110a9cd2013-07-03 02:23:441518 Local<Object> object = w->object();
1519 Local<Value> owner = object->Get(owner_sym);
Fedor Indutny2bc30f22013-10-16 16:57:261520 if (owner->IsUndefined())
1521 owner = object;
Ben Noordhuis110a9cd2013-07-03 02:23:441522 ary->Set(i++, owner);
Ben Noordhuis5f040652012-04-28 16:45:101523 }
1524
Ben Noordhuis110a9cd2013-07-03 02:23:441525 args.GetReturnValue().Set(ary);
Ben Noordhuis5f040652012-04-28 16:45:101526}
1527
1528
Ben Noordhuis110a9cd2013-07-03 02:23:441529static void Abort(const FunctionCallbackInfo<Value>& args) {
Robert Mustacchi22404862011-12-15 01:02:151530 abort();
1531}
1532
1533
Ben Noordhuis110a9cd2013-07-03 02:23:441534static void Chdir(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551535 Environment* env = Environment::GetCurrent(args);
Ryan Dahlb20c3432010-02-12 05:55:081536
Brandon Beacher47fcf782009-11-03 18:13:381537 if (args.Length() != 1 || !args[0]->IsString()) {
Caitlin Potterbe2404e2015-01-09 16:38:281538 return env->ThrowTypeError("Bad argument.");
Brandon Beacher47fcf782009-11-03 18:13:381539 }
Ryan Dahlb20c3432010-02-12 05:55:081540
Trevor Norriscbf76c12015-01-07 22:13:351541 node::Utf8Value path(args.GetIsolate(), args[0]);
Ben Noordhuisca9eb712013-07-18 21:18:501542 int err = uv_chdir(*path);
1543 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421544 return env->ThrowUVException(err, "uv_chdir");
Brandon Beacher47fcf782009-11-03 18:13:381545 }
Brandon Beacher47fcf782009-11-03 18:13:381546}
1547
Bert Beldercbcf4fe2011-11-24 01:19:541548
Ben Noordhuis110a9cd2013-07-03 02:23:441549static void Cwd(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551550 Environment* env = Environment::GetCurrent(args);
Bert Beldere84edd22011-12-01 23:24:441551#ifdef _WIN32
1552 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261553 char buf[MAX_PATH * 4];
Bert Beldere84edd22011-12-01 23:24:441554#else
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261555 char buf[PATH_MAX];
Bert Beldere84edd22011-12-01 23:24:441556#endif
Michael Carter8ea6adc2009-09-01 09:39:301557
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261558 size_t cwd_len = sizeof(buf);
1559 int err = uv_cwd(buf, &cwd_len);
Ben Noordhuisca9eb712013-07-18 21:18:501560 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421561 return env->ThrowUVException(err, "uv_cwd");
Michael Carter8ea6adc2009-09-01 09:39:301562 }
Peter Griess4e3c5d82010-07-12 15:47:451563
Saúl Ibarra Corretgéd2f2a322014-03-02 22:18:261564 Local<String> cwd = String::NewFromUtf8(env->isolate(),
1565 buf,
1566 String::kNormalString,
Saúl Ibarra Corretgée46cbaa2014-10-17 07:31:591567 cwd_len);
Ben Noordhuis110a9cd2013-07-03 02:23:441568 args.GetReturnValue().Set(cwd);
Michael Carter8ea6adc2009-09-01 09:39:301569}
1570
Bert Beldere84edd22011-12-01 23:24:441571
Ben Noordhuis110a9cd2013-07-03 02:23:441572static void Umask(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551573 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis110a9cd2013-07-03 02:23:441574 uint32_t old;
isaacs5f2e9092011-01-25 18:40:121575
Ryan Dahlacc120a2011-08-09 20:53:561576 if (args.Length() < 1 || args[0]->IsUndefined()) {
Rasmus Andersson374300c2010-02-27 17:18:411577 old = umask(0);
Ben Noordhuis110a9cd2013-07-03 02:23:441578 umask(static_cast<mode_t>(old));
Fedor Indutny8e29ce92013-07-31 18:07:291579 } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421580 return env->ThrowTypeError("argument must be an integer or octal string.");
isaacs5f2e9092011-01-25 18:40:121581 } else {
1582 int oct;
Fedor Indutny8e29ce92013-07-31 18:07:291583 if (args[0]->IsInt32()) {
isaacs5f2e9092011-01-25 18:40:121584 oct = args[0]->Uint32Value();
1585 } else {
1586 oct = 0;
Trevor Norriscbf76c12015-01-07 22:13:351587 node::Utf8Value str(env->isolate(), args[0]);
isaacs5f2e9092011-01-25 18:40:121588
1589 // Parse the octal string.
Timothy J Fontaine1a09da62014-06-10 23:36:041590 for (size_t i = 0; i < str.length(); i++) {
isaacs5f2e9092011-01-25 18:40:121591 char c = (*str)[i];
1592 if (c > '7' || c < '0') {
Fedor Indutny75adde02014-02-21 13:02:421593 return env->ThrowTypeError("invalid octal string");
isaacs5f2e9092011-01-25 18:40:121594 }
1595 oct *= 8;
1596 oct += c - '0';
1597 }
1598 }
1599 old = umask(static_cast<mode_t>(oct));
Friedemann Altrock0433d822009-11-22 18:52:521600 }
isaacs5f2e9092011-01-25 18:40:121601
Ben Noordhuis110a9cd2013-07-03 02:23:441602 args.GetReturnValue().Set(old);
Friedemann Altrock0433d822009-11-22 18:52:521603}
1604
Michael Cartera3860762010-02-08 06:13:101605
Linus Mårtensson5e4e8ec2013-05-08 12:10:071606#if defined(__POSIX__) && !defined(__ANDROID__)
Ryan Dahlacc120a2011-08-09 20:53:561607
Ben Noordhuis3ece1302012-12-04 05:36:231608static const uid_t uid_not_found = static_cast<uid_t>(-1);
1609static const gid_t gid_not_found = static_cast<gid_t>(-1);
1610
1611
1612static uid_t uid_by_name(const char* name) {
1613 struct passwd pwd;
1614 struct passwd* pp;
1615 char buf[8192];
Ben Noordhuis3ece1302012-12-04 05:36:231616
1617 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321618 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231619
Ben Noordhuis2d82cdf2014-10-22 01:29:321620 if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231621 return pp->pw_uid;
1622 }
1623
1624 return uid_not_found;
1625}
1626
1627
1628static char* name_by_uid(uid_t uid) {
1629 struct passwd pwd;
1630 struct passwd* pp;
1631 char buf[8192];
1632 int rc;
1633
1634 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321635 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231636
Ben Noordhuis2d82cdf2014-10-22 01:29:321637 if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1638 pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231639 return strdup(pp->pw_name);
1640 }
1641
1642 if (rc == 0) {
1643 errno = ENOENT;
1644 }
1645
Ben Noordhuis2d82cdf2014-10-22 01:29:321646 return nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231647}
1648
1649
1650static gid_t gid_by_name(const char* name) {
1651 struct group pwd;
1652 struct group* pp;
1653 char buf[8192];
Ben Noordhuis3ece1302012-12-04 05:36:231654
1655 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321656 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231657
Ben Noordhuis2d82cdf2014-10-22 01:29:321658 if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231659 return pp->gr_gid;
1660 }
1661
1662 return gid_not_found;
1663}
1664
1665
1666#if 0 // For future use.
1667static const char* name_by_gid(gid_t gid) {
1668 struct group pwd;
1669 struct group* pp;
1670 char buf[8192];
1671 int rc;
1672
1673 errno = 0;
Ben Noordhuis2d82cdf2014-10-22 01:29:321674 pp = nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231675
Ben Noordhuis2d82cdf2014-10-22 01:29:321676 if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1677 pp != nullptr) {
Ben Noordhuis3ece1302012-12-04 05:36:231678 return strdup(pp->gr_name);
1679 }
1680
1681 if (rc == 0) {
1682 errno = ENOENT;
1683 }
1684
Ben Noordhuis2d82cdf2014-10-22 01:29:321685 return nullptr;
Ben Noordhuis3ece1302012-12-04 05:36:231686}
1687#endif
1688
1689
1690static uid_t uid_by_name(Handle<Value> value) {
1691 if (value->IsUint32()) {
1692 return static_cast<uid_t>(value->Uint32Value());
1693 } else {
Trevor Norriscbf76c12015-01-07 22:13:351694 // TODO(trevnorris): Fix to not use GetCurrent().
1695 node::Utf8Value name(Isolate::GetCurrent(), value);
Ben Noordhuis3ece1302012-12-04 05:36:231696 return uid_by_name(*name);
1697 }
1698}
1699
1700
1701static gid_t gid_by_name(Handle<Value> value) {
1702 if (value->IsUint32()) {
1703 return static_cast<gid_t>(value->Uint32Value());
1704 } else {
Trevor Norriscbf76c12015-01-07 22:13:351705 // TODO(trevnorris): Fix to not use GetCurrent().
1706 node::Utf8Value name(Isolate::GetCurrent(), value);
Ben Noordhuis3ece1302012-12-04 05:36:231707 return gid_by_name(*name);
1708 }
1709}
1710
1711
Ben Noordhuis110a9cd2013-07-03 02:23:441712static void GetUid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis6df47412013-09-05 19:47:081713 // uid_t is an uint32_t on all supported platforms.
1714 args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
Michael Cartera3860762010-02-08 06:13:101715}
1716
Ryan Dahlacc120a2011-08-09 20:53:561717
Ben Noordhuis110a9cd2013-07-03 02:23:441718static void GetGid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis6df47412013-09-05 19:47:081719 // gid_t is an uint32_t on all supported platforms.
1720 args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
James Duncandf1c1e52010-02-23 22:45:021721}
1722
1723
Ben Noordhuis110a9cd2013-07-03 02:23:441724static void SetGid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551725 Environment* env = Environment::GetCurrent(args);
Ryan Dahl39943402010-03-15 19:49:401726
Ben Noordhuis3ece1302012-12-04 05:36:231727 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421728 return env->ThrowTypeError("setgid argument must be a number or a string");
James Duncandf1c1e52010-02-23 22:45:021729 }
1730
Ben Noordhuis3ece1302012-12-04 05:36:231731 gid_t gid = gid_by_name(args[0]);
Blake Mizerany8c853402010-06-30 06:12:461732
Ben Noordhuis3ece1302012-12-04 05:36:231733 if (gid == gid_not_found) {
Fedor Indutny75adde02014-02-21 13:02:421734 return env->ThrowError("setgid group id does not exist");
Peter Griess2420f072010-05-19 00:40:441735 }
1736
Ben Noordhuis3ece1302012-12-04 05:36:231737 if (setgid(gid)) {
Fedor Indutny75adde02014-02-21 13:02:421738 return env->ThrowErrnoException(errno, "setgid");
James Duncandf1c1e52010-02-23 22:45:021739 }
James Duncandf1c1e52010-02-23 22:45:021740}
Michael Cartera3860762010-02-08 06:13:101741
Ryan Dahlacc120a2011-08-09 20:53:561742
Ben Noordhuis110a9cd2013-07-03 02:23:441743static void SetUid(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551744 Environment* env = Environment::GetCurrent(args);
Michael Cartera3860762010-02-08 06:13:101745
Ben Noordhuis3ece1302012-12-04 05:36:231746 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421747 return env->ThrowTypeError("setuid argument must be a number or a string");
Michael Cartera3860762010-02-08 06:13:101748 }
1749
Ben Noordhuis3ece1302012-12-04 05:36:231750 uid_t uid = uid_by_name(args[0]);
Peter Griess2420f072010-05-19 00:40:441751
Ben Noordhuis3ece1302012-12-04 05:36:231752 if (uid == uid_not_found) {
Fedor Indutny75adde02014-02-21 13:02:421753 return env->ThrowError("setuid user id does not exist");
Peter Griess2420f072010-05-19 00:40:441754 }
1755
Ben Noordhuis3ece1302012-12-04 05:36:231756 if (setuid(uid)) {
Fedor Indutny75adde02014-02-21 13:02:421757 return env->ThrowErrnoException(errno, "setuid");
Michael Cartera3860762010-02-08 06:13:101758 }
Michael Cartera3860762010-02-08 06:13:101759}
1760
Ryan Dahlacc120a2011-08-09 20:53:561761
Ben Noordhuis110a9cd2013-07-03 02:23:441762static void GetGroups(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551763 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis3ece1302012-12-04 05:36:231764
Ben Noordhuis2d82cdf2014-10-22 01:29:321765 int ngroups = getgroups(0, nullptr);
Ben Noordhuis3ece1302012-12-04 05:36:231766
1767 if (ngroups == -1) {
Fedor Indutny75adde02014-02-21 13:02:421768 return env->ThrowErrnoException(errno, "getgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231769 }
1770
1771 gid_t* groups = new gid_t[ngroups];
1772
1773 ngroups = getgroups(ngroups, groups);
1774
1775 if (ngroups == -1) {
1776 delete[] groups;
Fedor Indutny75adde02014-02-21 13:02:421777 return env->ThrowErrnoException(errno, "getgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231778 }
1779
Fedor Indutnyce04c722014-03-13 16:38:141780 Local<Array> groups_list = Array::New(env->isolate(), ngroups);
Ben Noordhuis3ece1302012-12-04 05:36:231781 bool seen_egid = false;
1782 gid_t egid = getegid();
1783
1784 for (int i = 0; i < ngroups; i++) {
Fedor Indutnyce04c722014-03-13 16:38:141785 groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
Fedor Indutny2bc30f22013-10-16 16:57:261786 if (groups[i] == egid)
1787 seen_egid = true;
Ben Noordhuis3ece1302012-12-04 05:36:231788 }
1789
1790 delete[] groups;
1791
1792 if (seen_egid == false) {
Fedor Indutnyce04c722014-03-13 16:38:141793 groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
Ben Noordhuis3ece1302012-12-04 05:36:231794 }
1795
Ben Noordhuis110a9cd2013-07-03 02:23:441796 args.GetReturnValue().Set(groups_list);
Ben Noordhuis3ece1302012-12-04 05:36:231797}
1798
1799
Ben Noordhuis110a9cd2013-07-03 02:23:441800static void SetGroups(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551801 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis3ece1302012-12-04 05:36:231802
1803 if (!args[0]->IsArray()) {
Fedor Indutny75adde02014-02-21 13:02:421804 return env->ThrowTypeError("argument 1 must be an array");
Ben Noordhuis3ece1302012-12-04 05:36:231805 }
1806
1807 Local<Array> groups_list = args[0].As<Array>();
1808 size_t size = groups_list->Length();
1809 gid_t* groups = new gid_t[size];
1810
1811 for (size_t i = 0; i < size; i++) {
1812 gid_t gid = gid_by_name(groups_list->Get(i));
1813
1814 if (gid == gid_not_found) {
1815 delete[] groups;
Fedor Indutny75adde02014-02-21 13:02:421816 return env->ThrowError("group name not found");
Ben Noordhuis3ece1302012-12-04 05:36:231817 }
1818
1819 groups[i] = gid;
1820 }
1821
1822 int rc = setgroups(size, groups);
1823 delete[] groups;
1824
1825 if (rc == -1) {
Fedor Indutny75adde02014-02-21 13:02:421826 return env->ThrowErrnoException(errno, "setgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231827 }
Ben Noordhuis3ece1302012-12-04 05:36:231828}
1829
1830
Ben Noordhuis110a9cd2013-07-03 02:23:441831static void InitGroups(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551832 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis3ece1302012-12-04 05:36:231833
1834 if (!args[0]->IsUint32() && !args[0]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421835 return env->ThrowTypeError("argument 1 must be a number or a string");
Ben Noordhuis3ece1302012-12-04 05:36:231836 }
1837
1838 if (!args[1]->IsUint32() && !args[1]->IsString()) {
Fedor Indutny75adde02014-02-21 13:02:421839 return env->ThrowTypeError("argument 2 must be a number or a string");
Ben Noordhuis3ece1302012-12-04 05:36:231840 }
1841
Trevor Norriscbf76c12015-01-07 22:13:351842 node::Utf8Value arg0(env->isolate(), args[0]);
Ben Noordhuis3ece1302012-12-04 05:36:231843 gid_t extra_group;
1844 bool must_free;
1845 char* user;
1846
1847 if (args[0]->IsUint32()) {
1848 user = name_by_uid(args[0]->Uint32Value());
1849 must_free = true;
1850 } else {
1851 user = *arg0;
1852 must_free = false;
1853 }
1854
Ben Noordhuis2d82cdf2014-10-22 01:29:321855 if (user == nullptr) {
Fedor Indutny75adde02014-02-21 13:02:421856 return env->ThrowError("initgroups user not found");
Ben Noordhuis3ece1302012-12-04 05:36:231857 }
1858
1859 extra_group = gid_by_name(args[1]);
1860
1861 if (extra_group == gid_not_found) {
Fedor Indutny2bc30f22013-10-16 16:57:261862 if (must_free)
1863 free(user);
Fedor Indutny75adde02014-02-21 13:02:421864 return env->ThrowError("initgroups extra group not found");
Ben Noordhuis3ece1302012-12-04 05:36:231865 }
1866
1867 int rc = initgroups(user, extra_group);
1868
1869 if (must_free) {
1870 free(user);
1871 }
1872
1873 if (rc) {
Fedor Indutny75adde02014-02-21 13:02:421874 return env->ThrowErrnoException(errno, "initgroups");
Ben Noordhuis3ece1302012-12-04 05:36:231875 }
Ben Noordhuis3ece1302012-12-04 05:36:231876}
1877
Fedor Indutny8e29ce92013-07-31 18:07:291878#endif // __POSIX__ && !defined(__ANDROID__)
Bert Belder30bab522010-11-25 00:09:061879
Michael Cartera3860762010-02-08 06:13:101880
Ben Noordhuis110a9cd2013-07-03 02:23:441881void Exit(const FunctionCallbackInfo<Value>& args) {
Rasmus Christian Pedersen734fb492014-09-18 12:10:531882 exit(args[0]->Int32Value());
Ryan0f517032009-04-29 09:09:321883}
1884
Ryan Dahl3ac6dee2010-05-08 02:05:591885
Ben Noordhuis110a9cd2013-07-03 02:23:441886static void Uptime(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551887 Environment* env = Environment::GetCurrent(args);
Igor Zinkovsky500c8f42011-12-15 20:36:051888 double uptime;
Tom Hughescf78ce52011-03-04 23:57:541889
Fedor Indutny6a610a02014-10-04 14:44:391890 uv_update_time(env->event_loop());
1891 uptime = uv_now(env->event_loop()) - prog_start_time;
Tom Hughescf78ce52011-03-04 23:57:541892
Timothy J Fontaineb19b60a2014-05-01 20:54:231893 args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
Tom Hughescf78ce52011-03-04 23:57:541894}
Ryan Dahl3ac6dee2010-05-08 02:05:591895
Ryan Dahlc344fbc2011-10-06 21:59:381896
Ben Noordhuis110a9cd2013-07-03 02:23:441897void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551898 Environment* env = Environment::GetCurrent(args);
Ryan Dahlb3b3cfe2009-11-03 12:00:421899
Ryan Dahl5783a522011-10-18 21:30:311900 size_t rss;
Ben Noordhuisca9eb712013-07-18 21:18:501901 int err = uv_resident_set_memory(&rss);
1902 if (err) {
Fedor Indutny75adde02014-02-21 13:02:421903 return env->ThrowUVException(err, "uv_resident_set_memory");
Ryan Dahl3a701292009-11-03 00:30:011904 }
1905
Ryan Dahl38e425d2009-11-28 15:31:291906 // V8 memory usage
1907 HeapStatistics v8_heap_stats;
Fedor Indutny75adde02014-02-21 13:02:421908 env->isolate()->GetHeapStatistics(&v8_heap_stats);
Ben Noordhuis756b6222013-08-10 22:26:111909
1910 Local<Integer> heap_total =
Fedor Indutnyce04c722014-03-13 16:38:141911 Integer::NewFromUnsigned(env->isolate(), v8_heap_stats.total_heap_size());
Ben Noordhuis756b6222013-08-10 22:26:111912 Local<Integer> heap_used =
Fedor Indutnyce04c722014-03-13 16:38:141913 Integer::NewFromUnsigned(env->isolate(), v8_heap_stats.used_heap_size());
Ben Noordhuis756b6222013-08-10 22:26:111914
Fedor Indutnyce04c722014-03-13 16:38:141915 Local<Object> info = Object::New(env->isolate());
Fedor Indutny75adde02014-02-21 13:02:421916 info->Set(env->rss_string(), Number::New(env->isolate(), rss));
Ben Noordhuis756b6222013-08-10 22:26:111917 info->Set(env->heap_total_string(), heap_total);
1918 info->Set(env->heap_used_string(), heap_used);
Ryan Dahl38e425d2009-11-28 15:31:291919
Ben Noordhuis110a9cd2013-07-03 02:23:441920 args.GetReturnValue().Set(info);
Ryan Dahl3a701292009-11-03 00:30:011921}
Ryan Dahlb3b3cfe2009-11-03 12:00:421922
Bert Belder4a2cb072010-11-29 17:40:141923
Ben Noordhuis110a9cd2013-07-03 02:23:441924void Kill(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551925 Environment* env = Environment::GetCurrent(args);
Ryan Dahlb20c3432010-02-12 05:55:081926
Ryan Dahl4227e9d2010-12-21 23:40:101927 if (args.Length() != 2) {
Fedor Indutny75adde02014-02-21 13:02:421928 return env->ThrowError("Bad argument.");
Brandon Beacher334d56d2009-10-14 21:56:121929 }
Ryan Dahlb20c3432010-02-12 05:55:081930
Rasmus Christian Pedersen734fb492014-09-18 12:10:531931 int pid = args[0]->Int32Value();
Ryan Dahl6eca9482010-09-17 06:13:031932 int sig = args[1]->Int32Value();
Ben Noordhuisca9eb712013-07-18 21:18:501933 int err = uv_kill(pid, sig);
1934 args.GetReturnValue().Set(err);
Brandon Beacher334d56d2009-10-14 21:56:121935}
1936
Nathan Rajlich07c886f2012-03-05 16:51:581937// used in Hrtime() below
1938#define NANOS_PER_SEC 1000000000
1939
1940// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1941// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1942// so this function instead returns an Array with 2 entries representing seconds
1943// and nanoseconds, to avoid any integer overflow possibility.
1944// Pass in an Array from a previous hrtime() call to instead get a time diff.
Ben Noordhuis110a9cd2013-07-03 02:23:441945void Hrtime(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:551946 Environment* env = Environment::GetCurrent(args);
Nathan Rajlich07c886f2012-03-05 16:51:581947
1948 uint64_t t = uv_hrtime();
1949
1950 if (args.Length() > 0) {
1951 // return a time diff tuple
Nathan Rajlichd3d83d72012-07-08 02:57:021952 if (!args[0]->IsArray()) {
Fedor Indutny75adde02014-02-21 13:02:421953 return env->ThrowTypeError(
1954 "process.hrtime() only accepts an Array tuple.");
Nathan Rajlichd3d83d72012-07-08 02:57:021955 }
Nathan Rajlich07c886f2012-03-05 16:51:581956 Local<Array> inArray = Local<Array>::Cast(args[0]);
1957 uint64_t seconds = inArray->Get(0)->Uint32Value();
1958 uint64_t nanos = inArray->Get(1)->Uint32Value();
1959 t -= (seconds * NANOS_PER_SEC) + nanos;
1960 }
1961
Fedor Indutnyce04c722014-03-13 16:38:141962 Local<Array> tuple = Array::New(env->isolate(), 2);
1963 tuple->Set(0, Integer::NewFromUnsigned(env->isolate(), t / NANOS_PER_SEC));
1964 tuple->Set(1, Integer::NewFromUnsigned(env->isolate(), t % NANOS_PER_SEC));
Ben Noordhuis110a9cd2013-07-03 02:23:441965 args.GetReturnValue().Set(tuple);
Nathan Rajlich07c886f2012-03-05 16:51:581966}
1967
Keith M Wesolowski76b98462013-12-17 00:00:441968extern "C" void node_module_register(void* m) {
1969 struct node_module* mp = reinterpret_cast<struct node_module*>(m);
1970
1971 if (mp->nm_flags & NM_F_BUILTIN) {
1972 mp->nm_link = modlist_builtin;
1973 modlist_builtin = mp;
Thorsten Lorenz0fe7a0d2014-09-15 17:00:221974 } else if (!node_is_initialized) {
1975 // "Linked" modules are included as part of the node project.
1976 // Like builtins they are registered *before* node::Init runs.
1977 mp->nm_flags = NM_F_LINKED;
1978 mp->nm_link = modlist_linked;
1979 modlist_linked = mp;
Keith M Wesolowski76b98462013-12-17 00:00:441980 } else {
Keith M Wesolowski76b98462013-12-17 00:00:441981 modpending = mp;
1982 }
1983}
1984
1985struct node_module* get_builtin_module(const char* name) {
1986 struct node_module* mp;
1987
Ben Noordhuis2d82cdf2014-10-22 01:29:321988 for (mp = modlist_builtin; mp != nullptr; mp = mp->nm_link) {
Keith M Wesolowski76b98462013-12-17 00:00:441989 if (strcmp(mp->nm_modname, name) == 0)
1990 break;
1991 }
1992
Ben Noordhuis2d82cdf2014-10-22 01:29:321993 CHECK(mp == nullptr || (mp->nm_flags & NM_F_BUILTIN) != 0);
Keith M Wesolowski76b98462013-12-17 00:00:441994 return (mp);
1995}
Bert Belderdd93c532011-10-28 10:05:091996
Thorsten Lorenz0fe7a0d2014-09-15 17:00:221997struct node_module* get_linked_module(const char* name) {
1998 struct node_module* mp;
1999
Bert Belder9483bfe2014-12-09 04:57:172000 for (mp = modlist_linked; mp != nullptr; mp = mp->nm_link) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222001 if (strcmp(mp->nm_modname, name) == 0)
2002 break;
2003 }
2004
Bert Belder9483bfe2014-12-09 04:57:172005 CHECK(mp == nullptr || (mp->nm_flags & NM_F_LINKED) != 0);
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222006 return mp;
2007}
2008
Bert Belderdd93c532011-10-28 10:05:092009typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
Ryan2b6d7242009-06-20 13:07:102010
isaacs15508582013-01-24 23:40:582011// DLOpen is process.dlopen(module, filename).
2012// Used to load 'module.node' dynamically shared objects.
Ben Noordhuis756b6222013-08-10 22:26:112013//
2014// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2015// when two contexts try to load the same shared object. Maybe have a shadow
2016// cache that's a plain C list or hash table that's shared across contexts?
Ben Noordhuis110a9cd2013-07-03 02:23:442017void DLOpen(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:552018 Environment* env = Environment::GetCurrent(args);
Bert Belderdd93c532011-10-28 10:05:092019 uv_lib_t lib;
Ryan2b6d7242009-06-20 13:07:102020
Ben Noordhuisa60056d2014-12-11 14:29:522021 CHECK_EQ(modpending, nullptr);
2022
toastynerd9419e1f2015-01-19 18:17:452023 if (args.Length() != 2) {
Fedor Indutny75adde02014-02-21 13:02:422024 env->ThrowError("process.dlopen takes exactly 2 arguments.");
Keith M Wesolowski76b98462013-12-17 00:00:442025 return;
Bert Belderdd93c532011-10-28 10:05:092026 }
Ryana97dce72009-08-31 09:14:342027
Trevor Norrisd5533862015-01-07 21:29:582028 Local<Object> module = args[0]->ToObject(env->isolate()); // Cast
Trevor Norriscbf76c12015-01-07 22:13:352029 node::Utf8Value filename(env->isolate(), args[1]); // Cast
Ben Noordhuisa60056d2014-12-11 14:29:522030 const bool is_dlopen_error = uv_dlopen(*filename, &lib);
isaacs15508582013-01-24 23:40:582031
Ben Noordhuisa60056d2014-12-11 14:29:522032 // Objects containing v14 or later modules will have registered themselves
2033 // on the pending list. Activate all of them now. At present, only one
2034 // module per object is supported.
2035 node_module* const mp = modpending;
2036 modpending = nullptr;
Ryan2b6d7242009-06-20 13:07:102037
Ben Noordhuisa60056d2014-12-11 14:29:522038 if (is_dlopen_error) {
Ben Noordhuis756b6222013-08-10 22:26:112039 Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
Ben Noordhuis039fac62012-05-17 05:13:292040#ifdef _WIN32
2041 // Windows needs to add the filename into the error message
Trevor Norrisd5533862015-01-07 21:29:582042 errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
Fedor Indutny8e29ce92013-07-31 18:07:292043#endif // _WIN32
Fedor Indutny75adde02014-02-21 13:02:422044 env->isolate()->ThrowException(Exception::Error(errmsg));
Ben Noordhuis110a9cd2013-07-03 02:23:442045 return;
Ryan2b6d7242009-06-20 13:07:102046 }
2047
Ben Noordhuis2d82cdf2014-10-22 01:29:322048 if (mp == nullptr) {
Fedor Indutny75adde02014-02-21 13:02:422049 env->ThrowError("Module did not self-register.");
Keith M Wesolowski76b98462013-12-17 00:00:442050 return;
Paul Querna367b87d2010-07-13 08:33:512051 }
Keith M Wesolowski76b98462013-12-17 00:00:442052 if (mp->nm_version != NODE_MODULE_VERSION) {
Ben Noordhuisf6923472012-07-26 23:06:122053 char errmsg[1024];
2054 snprintf(errmsg,
2055 sizeof(errmsg),
2056 "Module version mismatch. Expected %d, got %d.",
Keith M Wesolowski76b98462013-12-17 00:00:442057 NODE_MODULE_VERSION, mp->nm_version);
Fedor Indutny75adde02014-02-21 13:02:422058 env->ThrowError(errmsg);
Keith M Wesolowski76b98462013-12-17 00:00:442059 return;
2060 }
2061 if (mp->nm_flags & NM_F_BUILTIN) {
Fedor Indutny75adde02014-02-21 13:02:422062 env->ThrowError("Built-in module self-registered.");
Keith M Wesolowski76b98462013-12-17 00:00:442063 return;
Ryan2b6d7242009-06-20 13:07:102064 }
Ryan2b6d7242009-06-20 13:07:102065
Keith M Wesolowski76b98462013-12-17 00:00:442066 mp->nm_dso_handle = lib.handle;
2067 mp->nm_link = modlist_addon;
2068 modlist_addon = mp;
2069
Ben Noordhuisa60056d2014-12-11 14:29:522070 Local<String> exports_string = env->exports_string();
Trevor Norrisd5533862015-01-07 21:29:582071 Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());
Ben Noordhuisa60056d2014-12-11 14:29:522072
Ben Noordhuis2d82cdf2014-10-22 01:29:322073 if (mp->nm_context_register_func != nullptr) {
Keith M Wesolowski76b98462013-12-17 00:00:442074 mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
Ben Noordhuis2d82cdf2014-10-22 01:29:322075 } else if (mp->nm_register_func != nullptr) {
Keith M Wesolowski76b98462013-12-17 00:00:442076 mp->nm_register_func(exports, module, mp->nm_priv);
Ben Noordhuis756b6222013-08-10 22:26:112077 } else {
Fedor Indutny75adde02014-02-21 13:02:422078 env->ThrowError("Module has no declared entry point.");
Keith M Wesolowski76b98462013-12-17 00:00:442079 return;
Ben Noordhuis756b6222013-08-10 22:26:112080 }
Ryan2b6d7242009-06-20 13:07:102081
Peter Griess4e3c5d82010-07-12 15:47:452082 // Tell coverity that 'handle' should not be freed when we return.
2083 // coverity[leaked_storage]
Ryan2b6d7242009-06-20 13:07:102084}
2085
Tim-Smartae10a482010-03-12 08:36:002086
Ryand6c9d312009-09-11 14:02:292087static void OnFatalError(const char* location, const char* message) {
Ryan Dahl53a841d2009-12-29 19:20:512088 if (location) {
2089 fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
2090 } else {
2091 fprintf(stderr, "FATAL ERROR: %s\n", message);
2092 }
Ben Noordhuisc56a96c2013-06-29 05:30:112093 fflush(stderr);
Ben Noordhuisc56a96c2013-06-29 05:30:112094 abort();
Ryan63a9cd32009-04-15 08:08:282095}
2096
Miroslav Bajtosc16963b2013-06-17 19:19:592097
Trevor Norrisfa10b752013-06-20 23:44:022098NO_RETURN void FatalError(const char* location, const char* message) {
2099 OnFatalError(location, message);
2100 // to supress compiler warning
2101 abort();
2102}
2103
2104
Fedor Indutny75adde02014-02-21 13:02:422105void FatalException(Isolate* isolate,
2106 Handle<Value> error,
2107 Handle<Message> message) {
2108 HandleScope scope(isolate);
Felix Geisendörfer2b252ac2009-11-14 22:07:542109
Fedor Indutny75adde02014-02-21 13:02:422110 Environment* env = Environment::GetCurrent(isolate);
Ben Noordhuis756b6222013-08-10 22:26:112111 Local<Object> process_object = env->process_object();
2112 Local<String> fatal_exception_string = env->fatal_exception_string();
2113 Local<Function> fatal_exception_function =
2114 process_object->Get(fatal_exception_string).As<Function>();
Ryan Dahl45a806a2009-12-09 08:02:212115
Ben Noordhuis756b6222013-08-10 22:26:112116 if (!fatal_exception_function->IsFunction()) {
isaacs4401bb42012-12-26 20:28:332117 // failed before the process._fatalException function was added!
2118 // this is probably pretty bad. Nothing to do but report and exit.
Fedor Indutnyf1de13b2014-02-05 16:38:332119 ReportException(env, error, message);
isaacs95862b22013-02-27 19:23:202120 exit(6);
Felix Geisendörfer2b252ac2009-11-14 22:07:542121 }
2122
isaacs4401bb42012-12-26 20:28:332123 TryCatch fatal_try_catch;
isaacs07be9fc2012-05-09 22:12:132124
Miroslav Bajtosc16963b2013-06-17 19:19:592125 // Do not call FatalException when _fatalException handler throws
2126 fatal_try_catch.SetVerbose(false);
2127
isaacs4401bb42012-12-26 20:28:332128 // this will return true if the JS layer handled it, false otherwise
Ben Noordhuis756b6222013-08-10 22:26:112129 Local<Value> caught =
2130 fatal_exception_function->Call(process_object, 1, &error);
isaacs4401bb42012-12-26 20:28:332131
2132 if (fatal_try_catch.HasCaught()) {
2133 // the fatal exception function threw, so we must exit
Fedor Indutnyf1de13b2014-02-05 16:38:332134 ReportException(env, fatal_try_catch);
isaacs95862b22013-02-27 19:23:202135 exit(7);
isaacs4401bb42012-12-26 20:28:332136 }
2137
2138 if (false == caught->BooleanValue()) {
Fedor Indutnyf1de13b2014-02-05 16:38:332139 ReportException(env, error, message);
isaacsb30a03e2013-09-07 00:47:562140 exit(1);
isaacs80a55e92012-04-07 02:23:162141 }
Ryane78917b2009-03-09 13:08:312142}
2143
Ryan0e9e9272009-04-04 14:53:432144
Fedor Indutny75adde02014-02-21 13:02:422145void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2146 HandleScope scope(isolate);
Fedor Indutny8e29ce92013-07-31 18:07:292147 // TODO(bajtos) do not call FatalException if try_catch is verbose
Miroslav Bajtosc16963b2013-06-17 19:19:592148 // (requires V8 API to expose getter for try_catch.is_verbose_)
Fedor Indutny75adde02014-02-21 13:02:422149 FatalException(isolate, try_catch.Exception(), try_catch.Message());
Miroslav Bajtosc16963b2013-06-17 19:19:592150}
2151
2152
2153void OnMessage(Handle<Message> message, Handle<Value> error) {
2154 // The current version of V8 sends messages for errors only
2155 // (thus `error` is always set).
Fedor Indutny75adde02014-02-21 13:02:422156 FatalException(Isolate::GetCurrent(), error, message);
Miroslav Bajtosc16963b2013-06-17 19:19:592157}
2158
2159
Ben Noordhuis110a9cd2013-07-03 02:23:442160static void Binding(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:552161 Environment* env = Environment::GetCurrent(args);
Ryan Dahl627fb5a2010-03-15 20:48:032162
Trevor Norrisd5533862015-01-07 21:29:582163 Local<String> module = args[0]->ToString(env->isolate());
Trevor Norriscbf76c12015-01-07 22:13:352164 node::Utf8Value module_v(env->isolate(), module);
Ryan Dahl627fb5a2010-03-15 20:48:032165
Ben Noordhuis756b6222013-08-10 22:26:112166 Local<Object> cache = env->binding_cache_object();
Ryan Dahl627fb5a2010-03-15 20:48:032167 Local<Object> exports;
2168
Ben Noordhuis110a9cd2013-07-03 02:23:442169 if (cache->Has(module)) {
Trevor Norrisd5533862015-01-07 21:29:582170 exports = cache->Get(module)->ToObject(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442171 args.GetReturnValue().Set(exports);
2172 return;
Ryan Dahlea9ee1f2011-07-28 02:30:322173 }
Ryan Dahl6eca9482010-09-17 06:13:032174
Ryan Dahlea9ee1f2011-07-28 02:30:322175 // Append a string to process.moduleLoadList
2176 char buf[1024];
Fedor Indutny8e29ce92013-07-31 18:07:292177 snprintf(buf, sizeof(buf), "Binding %s", *module_v);
Ben Noordhuis110a9cd2013-07-03 02:23:442178
Ben Noordhuis756b6222013-08-10 22:26:112179 Local<Array> modules = env->module_load_list_array();
Ben Noordhuis110a9cd2013-07-03 02:23:442180 uint32_t l = modules->Length();
Fedor Indutny75adde02014-02-21 13:02:422181 modules->Set(l, OneByteString(env->isolate(), buf));
Ryan Dahlea9ee1f2011-07-28 02:30:322182
Keith M Wesolowski76b98462013-12-17 00:00:442183 node_module* mod = get_builtin_module(*module_v);
Ben Noordhuis2d82cdf2014-10-22 01:29:322184 if (mod != nullptr) {
Fedor Indutnyce04c722014-03-13 16:38:142185 exports = Object::New(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:112186 // Internal bindings don't have a "module" object, only exports.
Ben Noordhuis2d82cdf2014-10-22 01:29:322187 CHECK_EQ(mod->nm_register_func, nullptr);
2188 CHECK_NE(mod->nm_context_register_func, nullptr);
Ben Noordhuis756b6222013-08-10 22:26:112189 Local<Value> unused = Undefined(env->isolate());
Keith M Wesolowski76b98462013-12-17 00:00:442190 mod->nm_context_register_func(exports, unused,
2191 env->context(), mod->nm_priv);
Ben Noordhuis110a9cd2013-07-03 02:23:442192 cache->Set(module, exports);
Ryan Dahl6eca9482010-09-17 06:13:032193 } else if (!strcmp(*module_v, "constants")) {
Fedor Indutnyce04c722014-03-13 16:38:142194 exports = Object::New(env->isolate());
Ryan Dahl6eca9482010-09-17 06:13:032195 DefineConstants(exports);
Ben Noordhuis110a9cd2013-07-03 02:23:442196 cache->Set(module, exports);
Ryan Dahlc90546f2010-03-15 21:22:502197 } else if (!strcmp(*module_v, "natives")) {
Fedor Indutnyce04c722014-03-13 16:38:142198 exports = Object::New(env->isolate());
Fedor Indutny75adde02014-02-21 13:02:422199 DefineJavaScript(env, exports);
Ben Noordhuis110a9cd2013-07-03 02:23:442200 cache->Set(module, exports);
Ryan Dahl627fb5a2010-03-15 20:48:032201 } else {
Jackson Tian962e6512014-08-01 11:26:092202 char errmsg[1024];
2203 snprintf(errmsg,
2204 sizeof(errmsg),
2205 "No such module: %s",
2206 *module_v);
2207 return env->ThrowError(errmsg);
Ryan Dahl627fb5a2010-03-15 20:48:032208 }
2209
Ben Noordhuis110a9cd2013-07-03 02:23:442210 args.GetReturnValue().Set(exports);
Ryan Dahl627fb5a2010-03-15 20:48:032211}
2212
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222213static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
2214 Environment* env = Environment::GetCurrent(args.GetIsolate());
2215
Trevor Norrisd5533862015-01-07 21:29:582216 Local<String> module = args[0]->ToString(env->isolate());
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222217
2218 Local<Object> cache = env->binding_cache_object();
2219 Local<Value> exports_v = cache->Get(module);
2220
2221 if (exports_v->IsObject())
2222 return args.GetReturnValue().Set(exports_v.As<Object>());
2223
Trevor Norriscbf76c12015-01-07 22:13:352224 node::Utf8Value module_v(env->isolate(), module);
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222225 node_module* mod = get_linked_module(*module_v);
2226
Bert Belder9483bfe2014-12-09 04:57:172227 if (mod == nullptr) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222228 char errmsg[1024];
2229 snprintf(errmsg,
2230 sizeof(errmsg),
2231 "No such module was linked: %s",
2232 *module_v);
2233 return env->ThrowError(errmsg);
2234 }
2235
2236 Local<Object> exports = Object::New(env->isolate());
2237
Bert Belder9483bfe2014-12-09 04:57:172238 if (mod->nm_context_register_func != nullptr) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222239 mod->nm_context_register_func(exports,
2240 module,
2241 env->context(),
2242 mod->nm_priv);
Bert Belder9483bfe2014-12-09 04:57:172243 } else if (mod->nm_register_func != nullptr) {
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222244 mod->nm_register_func(exports, module, mod->nm_priv);
2245 } else {
2246 return env->ThrowError("Linked module has no declared entry point.");
2247 }
2248
2249 cache->Set(module, exports);
2250
2251 args.GetReturnValue().Set(exports);
2252}
Ryan Dahle742d072009-10-09 11:25:042253
Ben Noordhuis110a9cd2013-07-03 02:23:442254static void ProcessTitleGetter(Local<String> property,
2255 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422256 Environment* env = Environment::GetCurrent(info.GetIsolate());
2257 HandleScope scope(env->isolate());
Igor Zinkovsky500c8f42011-12-15 20:36:052258 char buffer[512];
2259 uv_get_process_title(buffer, sizeof(buffer));
Fedor Indutny75adde02014-02-21 13:02:422260 info.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), buffer));
Ryan Dahl5185c152010-06-18 07:26:492261}
2262
2263
2264static void ProcessTitleSetter(Local<String> property,
2265 Local<Value> value,
Ben Noordhuis110a9cd2013-07-03 02:23:442266 const PropertyCallbackInfo<void>& info) {
Fedor Indutny75adde02014-02-21 13:02:422267 Environment* env = Environment::GetCurrent(info.GetIsolate());
2268 HandleScope scope(env->isolate());
Trevor Norriscbf76c12015-01-07 22:13:352269 node::Utf8Value title(env->isolate(), value);
Fedor Indutny8e29ce92013-07-31 18:07:292270 // TODO(piscisaureus): protect with a lock
Igor Zinkovsky500c8f42011-12-15 20:36:052271 uv_set_process_title(*title);
Ryan Dahl5185c152010-06-18 07:26:492272}
2273
2274
Ben Noordhuis110a9cd2013-07-03 02:23:442275static void EnvGetter(Local<String> property,
2276 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422277 Environment* env = Environment::GetCurrent(info.GetIsolate());
2278 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182279#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352280 node::Utf8Value key(env->isolate(), property);
Ben Noordhuisb4def482010-10-15 13:48:342281 const char* val = getenv(*key);
2282 if (val) {
Fedor Indutny75adde02014-02-21 13:02:422283 return info.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), val));
Ben Noordhuisb4def482010-10-15 13:48:342284 }
Bert Belder077f9d72012-02-15 22:34:182285#else // _WIN32
2286 String::Value key(property);
Fedor Indutny8e29ce92013-07-31 18:07:292287 WCHAR buffer[32767]; // The maximum size allowed for environment variables.
Bert Belder077f9d72012-02-15 22:34:182288 DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2289 buffer,
2290 ARRAY_SIZE(buffer));
2291 // If result >= sizeof buffer the buffer was too small. That should never
2292 // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2293 // not found.
2294 if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2295 result < ARRAY_SIZE(buffer)) {
Ben Noordhuisf674b092013-08-07 19:50:412296 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
Fedor Indutny75adde02014-02-21 13:02:422297 Local<String> rc = String::NewFromTwoByte(env->isolate(), two_byte_buffer);
Ben Noordhuisf674b092013-08-07 19:50:412298 return info.GetReturnValue().Set(rc);
Bert Belder077f9d72012-02-15 22:34:182299 }
2300#endif
Ben Noordhuisfee02db2012-06-29 15:29:322301 // Not found. Fetch from prototype.
Ben Noordhuis110a9cd2013-07-03 02:23:442302 info.GetReturnValue().Set(
2303 info.Data().As<Object>()->Get(property));
Ben Noordhuisb4def482010-10-15 13:48:342304}
2305
2306
Ben Noordhuis110a9cd2013-07-03 02:23:442307static void EnvSetter(Local<String> property,
2308 Local<Value> value,
2309 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422310 Environment* env = Environment::GetCurrent(info.GetIsolate());
2311 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182312#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352313 node::Utf8Value key(env->isolate(), property);
2314 node::Utf8Value val(env->isolate(), value);
Ben Noordhuisb4def482010-10-15 13:48:342315 setenv(*key, *val, 1);
Bert Belder077f9d72012-02-15 22:34:182316#else // _WIN32
2317 String::Value key(property);
2318 String::Value val(value);
2319 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2320 // Environment variables that start with '=' are read-only.
2321 if (key_ptr[0] != L'=') {
2322 SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
Ryan Dahle6b06bc2011-08-11 00:14:232323 }
Bert Belder30bab522010-11-25 00:09:062324#endif
Bert Belder077f9d72012-02-15 22:34:182325 // Whether it worked or not, always return rval.
Ben Noordhuis110a9cd2013-07-03 02:23:442326 info.GetReturnValue().Set(value);
Ben Noordhuisb4def482010-10-15 13:48:342327}
2328
2329
Ben Noordhuis110a9cd2013-07-03 02:23:442330static void EnvQuery(Local<String> property,
2331 const PropertyCallbackInfo<Integer>& info) {
Fedor Indutny75adde02014-02-21 13:02:422332 Environment* env = Environment::GetCurrent(info.GetIsolate());
2333 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442334 int32_t rc = -1; // Not found unless proven otherwise.
Bert Belder077f9d72012-02-15 22:34:182335#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352336 node::Utf8Value key(env->isolate(), property);
Fedor Indutny2bc30f22013-10-16 16:57:262337 if (getenv(*key))
2338 rc = 0;
Bert Belder077f9d72012-02-15 22:34:182339#else // _WIN32
2340 String::Value key(property);
2341 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
Ben Noordhuis2d82cdf2014-10-22 01:29:322342 if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
Bert Belder077f9d72012-02-15 22:34:182343 GetLastError() == ERROR_SUCCESS) {
Ben Noordhuis110a9cd2013-07-03 02:23:442344 rc = 0;
Bert Belder077f9d72012-02-15 22:34:182345 if (key_ptr[0] == L'=') {
2346 // Environment variables that start with '=' are hidden and read-only.
Ben Noordhuis110a9cd2013-07-03 02:23:442347 rc = static_cast<int32_t>(v8::ReadOnly) |
2348 static_cast<int32_t>(v8::DontDelete) |
2349 static_cast<int32_t>(v8::DontEnum);
Bert Belder077f9d72012-02-15 22:34:182350 }
2351 }
2352#endif
Fedor Indutny2bc30f22013-10-16 16:57:262353 if (rc != -1)
2354 info.GetReturnValue().Set(rc);
Ben Noordhuisb4def482010-10-15 13:48:342355}
2356
2357
Ben Noordhuis110a9cd2013-07-03 02:23:442358static void EnvDeleter(Local<String> property,
2359 const PropertyCallbackInfo<Boolean>& info) {
Fedor Indutny75adde02014-02-21 13:02:422360 Environment* env = Environment::GetCurrent(info.GetIsolate());
2361 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442362 bool rc = true;
Bert Belder30bab522010-11-25 00:09:062363#ifdef __POSIX__
Trevor Norriscbf76c12015-01-07 22:13:352364 node::Utf8Value key(env->isolate(), property);
Ben Noordhuis2d82cdf2014-10-22 01:29:322365 rc = getenv(*key) != nullptr;
Fedor Indutny2bc30f22013-10-16 16:57:262366 if (rc)
2367 unsetenv(*key);
Bert Belder30bab522010-11-25 00:09:062368#else
Bert Belder077f9d72012-02-15 22:34:182369 String::Value key(property);
2370 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
Ben Noordhuis2d82cdf2014-10-22 01:29:322371 if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, nullptr)) {
Bert Belder077f9d72012-02-15 22:34:182372 // Deletion failed. Return true if the key wasn't there in the first place,
2373 // false if it is still there.
Ben Noordhuis2d82cdf2014-10-22 01:29:322374 rc = GetEnvironmentVariableW(key_ptr, nullptr, 0) == 0 &&
Ben Noordhuis110a9cd2013-07-03 02:23:442375 GetLastError() != ERROR_SUCCESS;
Ben Noordhuisb4def482010-10-15 13:48:342376 }
Bert Belder077f9d72012-02-15 22:34:182377#endif
Ben Noordhuis110a9cd2013-07-03 02:23:442378 info.GetReturnValue().Set(rc);
Ben Noordhuisb4def482010-10-15 13:48:342379}
2380
2381
Ben Noordhuis110a9cd2013-07-03 02:23:442382static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
Fedor Indutny75adde02014-02-21 13:02:422383 Environment* env = Environment::GetCurrent(info.GetIsolate());
2384 HandleScope scope(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182385#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:342386 int size = 0;
Fedor Indutny2bc30f22013-10-16 16:57:262387 while (environ[size])
2388 size++;
Ben Noordhuisb4def482010-10-15 13:48:342389
Fedor Indutnyce04c722014-03-13 16:38:142390 Local<Array> envarr = Array::New(env->isolate(), size);
Ben Noordhuisb4def482010-10-15 13:48:342391
2392 for (int i = 0; i < size; ++i) {
2393 const char* var = environ[i];
2394 const char* s = strchr(var, '=');
2395 const int length = s ? s - var : strlen(var);
Fedor Indutny75adde02014-02-21 13:02:422396 Local<String> name = String::NewFromUtf8(env->isolate(),
Ben Noordhuisf674b092013-08-07 19:50:412397 var,
2398 String::kNormalString,
2399 length);
Fedor Indutny75adde02014-02-21 13:02:422400 envarr->Set(i, name);
Ben Noordhuisb4def482010-10-15 13:48:342401 }
Bert Belder077f9d72012-02-15 22:34:182402#else // _WIN32
2403 WCHAR* environment = GetEnvironmentStringsW();
Ben Noordhuis2d82cdf2014-10-22 01:29:322404 if (environment == nullptr)
Fedor Indutny2bc30f22013-10-16 16:57:262405 return; // This should not happen.
Fedor Indutnyce04c722014-03-13 16:38:142406 Local<Array> envarr = Array::New(env->isolate());
Bert Belder077f9d72012-02-15 22:34:182407 WCHAR* p = environment;
2408 int i = 0;
Nikolai Vavilovb105f6f2014-10-24 22:36:592409 while (*p) {
Bert Belder077f9d72012-02-15 22:34:182410 WCHAR *s;
2411 if (*p == L'=') {
2412 // If the key starts with '=' it is a hidden environment variable.
2413 p += wcslen(p) + 1;
2414 continue;
2415 } else {
2416 s = wcschr(p, L'=');
2417 }
2418 if (!s) {
2419 s = p + wcslen(p);
2420 }
Ben Noordhuisf674b092013-08-07 19:50:412421 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
Ben Noordhuis78f709d2013-08-09 15:43:102422 const size_t two_byte_buffer_len = s - p;
Fedor Indutny75adde02014-02-21 13:02:422423 Local<String> value = String::NewFromTwoByte(env->isolate(),
Ben Noordhuis78f709d2013-08-09 15:43:102424 two_byte_buffer,
2425 String::kNormalString,
2426 two_byte_buffer_len);
Fedor Indutny75adde02014-02-21 13:02:422427 envarr->Set(i++, value);
Bert Belder077f9d72012-02-15 22:34:182428 p = s + wcslen(s) + 1;
2429 }
2430 FreeEnvironmentStringsW(environment);
2431#endif
Ben Noordhuis110a9cd2013-07-03 02:23:442432
Fedor Indutny75adde02014-02-21 13:02:422433 info.GetReturnValue().Set(envarr);
Ben Noordhuisb4def482010-10-15 13:48:342434}
2435
2436
Fedor Indutny75adde02014-02-21 13:02:422437static Handle<Object> GetFeatures(Environment* env) {
Fedor Indutnyce04c722014-03-13 16:38:142438 EscapableHandleScope scope(env->isolate());
Ben Noordhuisaa0308d2011-07-23 21:16:482439
Fedor Indutnyce04c722014-03-13 16:38:142440 Local<Object> obj = Object::New(env->isolate());
Ryan Dahl52a40e02011-08-24 21:16:352441#if defined(DEBUG) && DEBUG
Fedor Indutny75adde02014-02-21 13:02:422442 Local<Value> debug = True(env->isolate());
Ryan Dahl52a40e02011-08-24 21:16:352443#else
Fedor Indutny75adde02014-02-21 13:02:422444 Local<Value> debug = False(env->isolate());
Fedor Indutny8e29ce92013-07-31 18:07:292445#endif // defined(DEBUG) && DEBUG
2446
Fedor Indutny75adde02014-02-21 13:02:422447 obj->Set(env->debug_string(), debug);
Ryan Dahl52a40e02011-08-24 21:16:352448
Fedor Indutny75adde02014-02-21 13:02:422449 obj->Set(env->uv_string(), True(env->isolate()));
Fedor Indutny8e29ce92013-07-31 18:07:292450 // TODO(bnoordhuis) ping libuv
Fedor Indutny75adde02014-02-21 13:02:422451 obj->Set(env->ipv6_lc_string(), True(env->isolate()));
Ben Noordhuisf674b092013-08-07 19:50:412452
Ben Noordhuis8d567f42013-08-27 14:14:452453#ifdef OPENSSL_NPN_NEGOTIATED
Fedor Indutny75adde02014-02-21 13:02:422454 Local<Boolean> tls_npn = True(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452455#else
Fedor Indutny75adde02014-02-21 13:02:422456 Local<Boolean> tls_npn = False(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452457#endif
Fedor Indutny75adde02014-02-21 13:02:422458 obj->Set(env->tls_npn_string(), tls_npn);
Ben Noordhuis8d567f42013-08-27 14:14:452459
2460#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
Fedor Indutny75adde02014-02-21 13:02:422461 Local<Boolean> tls_sni = True(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452462#else
Fedor Indutny75adde02014-02-21 13:02:422463 Local<Boolean> tls_sni = False(env->isolate());
Ben Noordhuis8d567f42013-08-27 14:14:452464#endif
Fedor Indutny75adde02014-02-21 13:02:422465 obj->Set(env->tls_sni_string(), tls_sni);
Ben Noordhuis8d567f42013-08-27 14:14:452466
Fedor Indutnyb3ef2892014-04-14 17:15:572467#if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2468 Local<Boolean> tls_ocsp = True(env->isolate());
2469#else
2470 Local<Boolean> tls_ocsp = False(env->isolate());
2471#endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2472 obj->Set(env->tls_ocsp_string(), tls_ocsp);
2473
Fedor Indutny75adde02014-02-21 13:02:422474 obj->Set(env->tls_string(),
Ben Noordhuis2d82cdf2014-10-22 01:29:322475 Boolean::New(env->isolate(),
2476 get_builtin_module("crypto") != nullptr));
Ben Noordhuisaa0308d2011-07-23 21:16:482477
Fedor Indutnyce04c722014-03-13 16:38:142478 return scope.Escape(obj);
Ben Noordhuisaa0308d2011-07-23 21:16:482479}
2480
2481
Ben Noordhuis110a9cd2013-07-03 02:23:442482static void DebugPortGetter(Local<String> property,
2483 const PropertyCallbackInfo<Value>& info) {
Fedor Indutny75adde02014-02-21 13:02:422484 Environment* env = Environment::GetCurrent(info.GetIsolate());
2485 HandleScope scope(env->isolate());
Ben Noordhuis110a9cd2013-07-03 02:23:442486 info.GetReturnValue().Set(debug_port);
Fedor Indutny3f43b1c2012-02-12 15:53:432487}
2488
2489
2490static void DebugPortSetter(Local<String> property,
2491 Local<Value> value,
Ben Noordhuis110a9cd2013-07-03 02:23:442492 const PropertyCallbackInfo<void>& info) {
Fedor Indutny75adde02014-02-21 13:02:422493 Environment* env = Environment::GetCurrent(info.GetIsolate());
2494 HandleScope scope(env->isolate());
Rasmus Christian Pedersen734fb492014-09-18 12:10:532495 debug_port = value->Int32Value();
Fedor Indutny3f43b1c2012-02-12 15:53:432496}
2497
2498
Ben Noordhuis110a9cd2013-07-03 02:23:442499static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2500static void DebugPause(const FunctionCallbackInfo<Value>& args);
2501static void DebugEnd(const FunctionCallbackInfo<Value>& args);
Bert Belder829735e2011-11-04 15:23:022502
Shigeki Ohtsucd372512013-02-06 02:13:022503
Ben Noordhuis110a9cd2013-07-03 02:23:442504void NeedImmediateCallbackGetter(Local<String> property,
2505 const PropertyCallbackInfo<Value>& info) {
Ben Noordhuis756b6222013-08-10 22:26:112506 Environment* env = Environment::GetCurrent(info.GetIsolate());
2507 const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2508 bool active = uv_is_active(
2509 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2510 info.GetReturnValue().Set(active);
Shigeki Ohtsucd372512013-02-06 02:13:022511}
2512
2513
Ben Noordhuis756b6222013-08-10 22:26:112514static void NeedImmediateCallbackSetter(
2515 Local<String> property,
2516 Local<Value> value,
2517 const PropertyCallbackInfo<void>& info) {
Ben Noordhuis756b6222013-08-10 22:26:112518 HandleScope handle_scope(info.GetIsolate());
Ben Noordhuis09724b32013-11-11 21:02:032519 Environment* env = Environment::GetCurrent(info.GetIsolate());
Shigeki Ohtsucd372512013-02-06 02:13:022520
Ben Noordhuis756b6222013-08-10 22:26:112521 uv_check_t* immediate_check_handle = env->immediate_check_handle();
2522 bool active = uv_is_active(
2523 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
Shigeki Ohtsucd372512013-02-06 02:13:022524
Ben Noordhuis756b6222013-08-10 22:26:112525 if (active == value->BooleanValue())
2526 return;
Shigeki Ohtsucd372512013-02-06 02:13:022527
Ben Noordhuis756b6222013-08-10 22:26:112528 uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
Shigeki Ohtsucd372512013-02-06 02:13:022529
Ben Noordhuis756b6222013-08-10 22:26:112530 if (active) {
2531 uv_check_stop(immediate_check_handle);
2532 uv_idle_stop(immediate_idle_handle);
Shigeki Ohtsucd372512013-02-06 02:13:022533 } else {
Ben Noordhuis756b6222013-08-10 22:26:112534 uv_check_start(immediate_check_handle, CheckImmediate);
2535 // Idle handle is needed only to stop the event loop from blocking in poll.
2536 uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
Shigeki Ohtsucd372512013-02-06 02:13:022537 }
2538}
2539
2540
Saúl Ibarra Corretgé42b93432014-03-12 23:08:292541void SetIdle(uv_prepare_t* handle) {
Ben Noordhuisf6496262013-10-03 09:03:462542 Environment* env = Environment::from_idle_prepare_handle(handle);
2543 env->isolate()->GetCpuProfiler()->SetIdle(true);
2544}
2545
2546
Saúl Ibarra Corretgé42b93432014-03-12 23:08:292547void ClearIdle(uv_check_t* handle) {
Ben Noordhuisf6496262013-10-03 09:03:462548 Environment* env = Environment::from_idle_check_handle(handle);
2549 env->isolate()->GetCpuProfiler()->SetIdle(false);
2550}
2551
2552
2553void StartProfilerIdleNotifier(Environment* env) {
2554 uv_prepare_start(env->idle_prepare_handle(), SetIdle);
2555 uv_check_start(env->idle_check_handle(), ClearIdle);
2556}
2557
2558
2559void StopProfilerIdleNotifier(Environment* env) {
2560 uv_prepare_stop(env->idle_prepare_handle());
2561 uv_check_stop(env->idle_check_handle());
2562}
2563
2564
2565void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:552566 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis09724b32013-11-11 21:02:032567 StartProfilerIdleNotifier(env);
Ben Noordhuisf6496262013-10-03 09:03:462568}
2569
2570
2571void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:552572 Environment* env = Environment::GetCurrent(args);
Ben Noordhuis09724b32013-11-11 21:02:032573 StopProfilerIdleNotifier(env);
Ben Noordhuisf6496262013-10-03 09:03:462574}
2575
2576
Trevor Norrisc80f8fa2013-08-01 21:53:522577#define READONLY_PROPERTY(obj, str, var) \
2578 do { \
Fedor Indutny383b0c02014-10-08 10:34:512579 obj->ForceSet(OneByteString(env->isolate(), str), var, v8::ReadOnly); \
Trevor Norrisc80f8fa2013-08-01 21:53:522580 } while (0)
2581
2582
Ben Noordhuis756b6222013-08-10 22:26:112583void SetupProcessObject(Environment* env,
2584 int argc,
2585 const char* const* argv,
2586 int exec_argc,
2587 const char* const* exec_argv) {
Fedor Indutny75adde02014-02-21 13:02:422588 HandleScope scope(env->isolate());
Ryan Dahlcd1ec272011-01-02 09:44:422589
Ben Noordhuis756b6222013-08-10 22:26:112590 Local<Object> process = env->process_object();
Ben Noordhuis74a82152012-02-03 15:32:002591
Fedor Indutny75adde02014-02-21 13:02:422592 process->SetAccessor(env->title_string(),
Ryan Dahl5185c152010-06-18 07:26:492593 ProcessTitleGetter,
2594 ProcessTitleSetter);
2595
Ryan Dahlf4811832009-11-02 23:21:002596 // process.version
Ben Noordhuisf674b092013-08-07 19:50:412597 READONLY_PROPERTY(process,
2598 "version",
Fedor Indutny75adde02014-02-21 13:02:422599 FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
Ryan Dahl39b432e2010-08-17 18:24:102600
Ryan Dahlea9ee1f2011-07-28 02:30:322601 // process.moduleLoadList
Ben Noordhuis756b6222013-08-10 22:26:112602 READONLY_PROPERTY(process,
2603 "moduleLoadList",
2604 env->module_load_list_array());
Ryan Dahlea9ee1f2011-07-28 02:30:322605
Nathan Rajlich35043ad2012-03-13 23:04:172606 // process.versions
Fedor Indutnyce04c722014-03-13 16:38:142607 Local<Object> versions = Object::New(env->isolate());
Trevor Norrisc80f8fa2013-08-01 21:53:522608 READONLY_PROPERTY(process, "versions", versions);
Ben Noordhuisf674b092013-08-07 19:50:412609
2610 const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2611 "."
Johan Bergströmc0a9d1b2015-01-26 23:08:442612 NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
2613 "."
2614 NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
Ben Noordhuisf674b092013-08-07 19:50:412615 READONLY_PROPERTY(versions,
2616 "http_parser",
Fedor Indutny75adde02014-02-21 13:02:422617 FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
Ben Noordhuisf674b092013-08-07 19:50:412618
Ryan Dahl39b432e2010-08-17 18:24:102619 // +1 to get rid of the leading 'v'
Ben Noordhuisf674b092013-08-07 19:50:412620 READONLY_PROPERTY(versions,
2621 "node",
Fedor Indutny75adde02014-02-21 13:02:422622 OneByteString(env->isolate(), NODE_VERSION + 1));
Ben Noordhuisf674b092013-08-07 19:50:412623 READONLY_PROPERTY(versions,
2624 "v8",
Fedor Indutny75adde02014-02-21 13:02:422625 OneByteString(env->isolate(), V8::GetVersion()));
Ben Noordhuisf674b092013-08-07 19:50:412626 READONLY_PROPERTY(versions,
2627 "uv",
Fedor Indutny75adde02014-02-21 13:02:422628 OneByteString(env->isolate(), uv_version_string()));
Ben Noordhuisf674b092013-08-07 19:50:412629 READONLY_PROPERTY(versions,
2630 "zlib",
Fedor Indutny75adde02014-02-21 13:02:422631 FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
Johan Bergström01736dd2015-01-14 00:12:052632 READONLY_PROPERTY(versions,
2633 "ares",
2634 FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
Ben Noordhuisf674b092013-08-07 19:50:412635
2636 const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
Fedor Indutny75adde02014-02-21 13:02:422637 READONLY_PROPERTY(
2638 versions,
2639 "modules",
2640 FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
Ben Noordhuisf674b092013-08-07 19:50:412641
Peter Bright13d6a1f2011-08-06 04:23:252642#if HAVE_OPENSSL
Ryan Dahlcd1ec272011-01-02 09:44:422643 // Stupid code to slice out the version string.
Ben Noordhuis7acdabb2013-11-04 21:42:482644 { // NOLINT(whitespace/braces)
Ben Noordhuis962686b2013-11-03 20:00:372645 size_t i, j, k;
2646 int c;
2647 for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
2648 c = OPENSSL_VERSION_TEXT[i];
2649 if ('0' <= c && c <= '9') {
2650 for (j = i + 1; j < k; ++j) {
2651 c = OPENSSL_VERSION_TEXT[j];
2652 if (c == ' ')
2653 break;
2654 }
2655 break;
Ryan Dahlcd1ec272011-01-02 09:44:422656 }
Ryan Dahlcd1ec272011-01-02 09:44:422657 }
Ben Noordhuis962686b2013-11-03 20:00:372658 READONLY_PROPERTY(
2659 versions,
2660 "openssl",
Fedor Indutny75adde02014-02-21 13:02:422661 OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
Ryan Dahlcd1ec272011-01-02 09:44:422662 }
Ryan Dahlcd1ec272011-01-02 09:44:422663#endif
Ryan Dahl39b432e2010-08-17 18:24:102664
Nathan Rajlichb1be5402011-04-26 03:24:512665 // process.arch
Bert Beldere1fe2702015-01-08 12:05:512666 READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH));
Nathan Rajlichb1be5402011-04-26 03:24:512667
Ryan Dahlf4811832009-11-02 23:21:002668 // process.platform
Vladimir Kurchatkin9f457992015-01-09 12:38:092669 READONLY_PROPERTY(process,
2670 "platform",
2671 OneByteString(env->isolate(), NODE_PLATFORM));
Ryan Dahlf4811832009-11-02 23:21:002672
Ryan Dahlf3ad6352010-02-03 20:19:082673 // process.argv
Fedor Indutnyce04c722014-03-13 16:38:142674 Local<Array> arguments = Array::New(env->isolate(), argc);
Ben Noordhuis185c5152013-09-02 14:42:012675 for (int i = 0; i < argc; ++i) {
Fedor Indutny75adde02014-02-21 13:02:422676 arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
Ryan27b268b2009-06-17 13:05:442677 }
Fedor Indutny75adde02014-02-21 13:02:422678 process->Set(env->argv_string(), arguments);
Ryan27b268b2009-06-17 13:05:442679
Micheil Smith19fd5302012-03-05 17:53:152680 // process.execArgv
Fedor Indutnyce04c722014-03-13 16:38:142681 Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
Ben Noordhuis185c5152013-09-02 14:42:012682 for (int i = 0; i < exec_argc; ++i) {
Fedor Indutny75adde02014-02-21 13:02:422683 exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
Micheil Smith19fd5302012-03-05 17:53:152684 }
Fedor Indutny75adde02014-02-21 13:02:422685 process->Set(env->exec_argv_string(), exec_arguments);
Micheil Smith19fd5302012-03-05 17:53:152686
Ryan Dahlf3ad6352010-02-03 20:19:082687 // create process.env
Fedor Indutnyce04c722014-03-13 16:38:142688 Local<ObjectTemplate> process_env_template =
2689 ObjectTemplate::New(env->isolate());
Ben Noordhuis756b6222013-08-10 22:26:112690 process_env_template->SetNamedPropertyHandler(EnvGetter,
2691 EnvSetter,
2692 EnvQuery,
2693 EnvDeleter,
2694 EnvEnumerator,
Fedor Indutnyce04c722014-03-13 16:38:142695 Object::New(env->isolate()));
Ben Noordhuis756b6222013-08-10 22:26:112696 Local<Object> process_env = process_env_template->NewInstance();
Fedor Indutny75adde02014-02-21 13:02:422697 process->Set(env->env_string(), process_env);
Ryan Dahlf3ad6352010-02-03 20:19:082698
Fedor Indutnyce04c722014-03-13 16:38:142699 READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
Fedor Indutny75adde02014-02-21 13:02:422700 READONLY_PROPERTY(process, "features", GetFeatures(env));
2701 process->SetAccessor(env->need_imm_cb_string(),
Ben Noordhuisf674b092013-08-07 19:50:412702 NeedImmediateCallbackGetter,
2703 NeedImmediateCallbackSetter);
Ryandc39e822009-09-10 12:07:352704
TJ Holowaychuk9481bc12010-10-07 02:05:012705 // -e, --eval
2706 if (eval_string) {
Ben Noordhuisf674b092013-08-07 19:50:412707 READONLY_PROPERTY(process,
2708 "_eval",
Fedor Indutny75adde02014-02-21 13:02:422709 String::NewFromUtf8(env->isolate(), eval_string));
Nathan Rajlichef3a8742012-04-24 08:24:132710 }
2711
2712 // -p, --print
2713 if (print_eval) {
Fedor Indutny75adde02014-02-21 13:02:422714 READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
TJ Holowaychuk9481bc12010-10-07 02:05:012715 }
2716
Nathan Rajlich6292df62012-04-24 08:32:332717 // -i, --interactive
Nathan Rajlichfeaa8a42012-03-21 07:05:252718 if (force_repl) {
Fedor Indutny75adde02014-02-21 13:02:422719 READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
Nathan Rajlichfeaa8a42012-03-21 07:05:252720 }
2721
isaacs5b399292012-06-21 18:42:332722 // --no-deprecation
2723 if (no_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422724 READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
isaacs5b399292012-06-21 18:42:332725 }
2726
isaacs5038f402013-03-06 01:46:372727 // --throw-deprecation
2728 if (throw_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422729 READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
isaacs5038f402013-03-06 01:46:372730 }
2731
isaacs5b399292012-06-21 18:42:332732 // --trace-deprecation
2733 if (trace_deprecation) {
Fedor Indutny75adde02014-02-21 13:02:422734 READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
isaacs5b399292012-06-21 18:42:332735 }
2736
Ben Noordhuisf674b092013-08-07 19:50:412737 size_t exec_path_len = 2 * PATH_MAX;
2738 char* exec_path = new char[exec_path_len];
2739 Local<String> exec_path_value;
2740 if (uv_exepath(exec_path, &exec_path_len) == 0) {
Fedor Indutny75adde02014-02-21 13:02:422741 exec_path_value = String::NewFromUtf8(env->isolate(),
Ben Noordhuisf674b092013-08-07 19:50:412742 exec_path,
2743 String::kNormalString,
2744 exec_path_len);
Marshall Culpepperca35ba62010-06-22 06:31:192745 } else {
Fedor Indutny75adde02014-02-21 13:02:422746 exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
Marshall Culpepperca35ba62010-06-22 06:31:192747 }
Fedor Indutny75adde02014-02-21 13:02:422748 process->Set(env->exec_path_string(), exec_path_value);
Ben Noordhuisf674b092013-08-07 19:50:412749 delete[] exec_path;
Marshall Culpepperca35ba62010-06-22 06:31:192750
Fedor Indutny75adde02014-02-21 13:02:422751 process->SetAccessor(env->debug_port_string(),
Fedor Indutny3f43b1c2012-02-12 15:53:432752 DebugPortGetter,
2753 DebugPortSetter);
2754
Ryan Dahl38814552009-10-09 15:15:472755 // define various internal methods
Ben Noordhuisd3c317e2014-10-13 13:19:552756 env->SetMethod(process,
2757 "_startProfilerIdleNotifier",
2758 StartProfilerIdleNotifier);
2759 env->SetMethod(process,
2760 "_stopProfilerIdleNotifier",
2761 StopProfilerIdleNotifier);
2762 env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
2763 env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
2764 env->SetMethod(process, "reallyExit", Exit);
2765 env->SetMethod(process, "abort", Abort);
2766 env->SetMethod(process, "chdir", Chdir);
2767 env->SetMethod(process, "cwd", Cwd);
Bert Belder30bab522010-11-25 00:09:062768
Ben Noordhuisd3c317e2014-10-13 13:19:552769 env->SetMethod(process, "umask", Umask);
Ryan Dahlacc120a2011-08-09 20:53:562770
Linus Mårtensson5e4e8ec2013-05-08 12:10:072771#if defined(__POSIX__) && !defined(__ANDROID__)
Ben Noordhuisd3c317e2014-10-13 13:19:552772 env->SetMethod(process, "getuid", GetUid);
2773 env->SetMethod(process, "setuid", SetUid);
James Duncandf1c1e52010-02-23 22:45:022774
Ben Noordhuisd3c317e2014-10-13 13:19:552775 env->SetMethod(process, "setgid", SetGid);
2776 env->SetMethod(process, "getgid", GetGid);
Ben Noordhuis3ece1302012-12-04 05:36:232777
Ben Noordhuisd3c317e2014-10-13 13:19:552778 env->SetMethod(process, "getgroups", GetGroups);
2779 env->SetMethod(process, "setgroups", SetGroups);
2780 env->SetMethod(process, "initgroups", InitGroups);
Fedor Indutny8e29ce92013-07-31 18:07:292781#endif // __POSIX__ && !defined(__ANDROID__)
James Duncandf1c1e52010-02-23 22:45:022782
Ben Noordhuisd3c317e2014-10-13 13:19:552783 env->SetMethod(process, "_kill", Kill);
Bert Belder30bab522010-11-25 00:09:062784
Ben Noordhuisd3c317e2014-10-13 13:19:552785 env->SetMethod(process, "_debugProcess", DebugProcess);
2786 env->SetMethod(process, "_debugPause", DebugPause);
2787 env->SetMethod(process, "_debugEnd", DebugEnd);
Bert Belder829735e2011-11-04 15:23:022788
Ben Noordhuisd3c317e2014-10-13 13:19:552789 env->SetMethod(process, "hrtime", Hrtime);
Nathan Rajlich07c886f2012-03-05 16:51:582790
Ben Noordhuisd3c317e2014-10-13 13:19:552791 env->SetMethod(process, "dlopen", DLOpen);
Bert Belderdd93c532011-10-28 10:05:092792
Ben Noordhuisd3c317e2014-10-13 13:19:552793 env->SetMethod(process, "uptime", Uptime);
2794 env->SetMethod(process, "memoryUsage", MemoryUsage);
Ryan27b268b2009-06-17 13:05:442795
Ben Noordhuisd3c317e2014-10-13 13:19:552796 env->SetMethod(process, "binding", Binding);
Thorsten Lorenz0fe7a0d2014-09-15 17:00:222797 env->SetMethod(process, "_linkedBinding", LinkedBinding);
Ryan Dahl627fb5a2010-03-15 20:48:032798
Ben Noordhuisd3c317e2014-10-13 13:19:552799 env->SetMethod(process, "_setupNextTick", SetupNextTick);
2800 env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
Trevor Norrisf0b68892013-03-26 05:32:412801
Trevor Norris4f7f8bb2013-02-26 17:47:362802 // pre-set _events object for faster emit checks
Fedor Indutnyce04c722014-03-13 16:38:142803 process->Set(env->events_string(), Object::New(env->isolate()));
Dean McNameef67e8f22011-03-15 22:39:162804}
2805
2806
Trevor Norrisc80f8fa2013-08-01 21:53:522807#undef READONLY_PROPERTY
2808
2809
Dean McNameef67e8f22011-03-15 22:39:162810static void AtExit() {
Ryan Dahl4e43afd2011-09-30 20:11:472811 uv_tty_reset_mode();
Dean McNameef67e8f22011-03-15 22:39:162812}
2813
2814
Geir Haugec61b0e92014-03-31 07:52:032815static void SignalExit(int signo) {
Ryan Dahl4e43afd2011-09-30 20:11:472816 uv_tty_reset_mode();
Geir Haugec61b0e92014-03-31 07:52:032817 raise(signo);
Dean McNameef67e8f22011-03-15 22:39:162818}
2819
2820
isaacs906a1752013-08-21 22:36:502821// Most of the time, it's best to use `console.error` to write
2822// to the process.stderr stream. However, in some cases, such as
2823// when debugging the stream.Writable class or the process.nextTick
2824// function, it is useful to bypass JavaScript entirely.
2825static void RawDebug(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuis5fdff382014-10-11 14:52:072826 CHECK(args.Length() == 1 && args[0]->IsString() &&
2827 "must be called with a single string");
Trevor Norriscbf76c12015-01-07 22:13:352828 node::Utf8Value message(args.GetIsolate(), args[0]);
isaacs906a1752013-08-21 22:36:502829 fprintf(stderr, "%s\n", *message);
2830 fflush(stderr);
2831}
2832
2833
Fedor Indutny6a610a02014-10-04 14:44:392834void LoadEnvironment(Environment* env) {
Fedor Indutny75adde02014-02-21 13:02:422835 HandleScope handle_scope(env->isolate());
Ben Noordhuis34b0a362013-07-29 03:07:072836
Trevor Norrisd5533862015-01-07 21:29:582837 env->isolate()->SetFatalErrorHandler(node::OnFatalError);
2838 env->isolate()->AddMessageListener(OnMessage);
Fedor Indutny6a610a02014-10-04 14:44:392839
Ryan Dahl9f5643f2010-01-31 07:22:342840 // Compile, execute the src/node.js file. (Which was included as static C
2841 // string in node_natives.h. 'natve_node' is the string containing that
2842 // source code.)
Ryan Dahlb20c3432010-02-12 05:55:082843
Ryan Dahl9f5643f2010-01-31 07:22:342844 // The node.js file returns a function 'f'
Dean McNameef67e8f22011-03-15 22:39:162845 atexit(AtExit);
2846
Ryan Dahl9f5643f2010-01-31 07:22:342847 TryCatch try_catch;
Ryan Dahl9f5643f2010-01-31 07:22:342848
Miroslav Bajtosc16963b2013-06-17 19:19:592849 // Disable verbose mode to stop FatalException() handler from trying
2850 // to handle the exception. Errors this early in the start-up phase
2851 // are not safe to ignore.
2852 try_catch.SetVerbose(false);
2853
Fedor Indutnyf1de13b2014-02-05 16:38:332854 Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js");
Fedor Indutny75adde02014-02-21 13:02:422855 Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
Ryan Dahl9f5643f2010-01-31 07:22:342856 if (try_catch.HasCaught()) {
Fedor Indutnyf1de13b2014-02-05 16:38:332857 ReportException(env, try_catch);
Ryan Dahl9f5643f2010-01-31 07:22:342858 exit(10);
2859 }
Ben Noordhuis5fdff382014-10-11 14:52:072860 CHECK(f_value->IsFunction());
Ryan Dahl9f5643f2010-01-31 07:22:342861 Local<Function> f = Local<Function>::Cast(f_value);
2862
2863 // Now we call 'f' with the 'process' variable that we've built up with
2864 // all our bindings. Inside node.js we'll take care of assigning things to
2865 // their places.
Ryan Dahlb20c3432010-02-12 05:55:082866
Ryan Dahl9f5643f2010-01-31 07:22:342867 // We start the process this way in order to be more modular. Developers
2868 // who do not like how 'src/node.js' setups the module system but do like
2869 // Node's I/O bindings may want to replace 'f' with their own function.
2870
Ryan Dahlf8ce8482010-09-17 07:01:072871 // Add a reference to the global object
Ben Noordhuis756b6222013-08-10 22:26:112872 Local<Object> global = env->context()->Global();
Zoran Tomicicd98ea702010-02-22 05:15:442873
Ben Noordhuisc4def502013-10-28 19:18:592874#if defined HAVE_DTRACE || defined HAVE_ETW
Fedor Indutny75adde02014-02-21 13:02:422875 InitDTrace(env, global);
Ryan Dahle9257b82011-02-10 02:50:262876#endif
Ryan Dahl068b7332011-01-25 01:50:102877
Glen Keane5e825d12015-01-22 12:35:162878#if defined HAVE_LTTNG
2879 InitLTTNG(env, global);
2880#endif
2881
Scott Blomquistf657ce62012-11-20 23:27:222882#if defined HAVE_PERFCTR
Fedor Indutny75adde02014-02-21 13:02:422883 InitPerfCounters(env, global);
Scott Blomquistf657ce62012-11-20 23:27:222884#endif
2885
Miroslav Bajtosc16963b2013-06-17 19:19:592886 // Enable handling of uncaught exceptions
2887 // (FatalException(), break on uncaught exception in debugger)
2888 //
2889 // This is not strictly necessary since it's almost impossible
2890 // to attach the debugger fast enought to break on exception
2891 // thrown during process startup.
2892 try_catch.SetVerbose(true);
Ryan Dahl9f5643f2010-01-31 07:22:342893
Ben Noordhuisd3c317e2014-10-13 13:19:552894 env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
isaacs906a1752013-08-21 22:36:502895
Ben Noordhuis756b6222013-08-10 22:26:112896 Local<Value> arg = env->process_object();
Ben Noordhuis110a9cd2013-07-03 02:23:442897 f->Call(global, 1, &arg);
Ryan27b268b2009-06-17 13:05:442898}
2899
Zoran Tomicicd98ea702010-02-22 05:15:442900static void PrintHelp();
2901
Ben Noordhuisbd9c6662013-11-16 13:39:412902static bool ParseDebugOpt(const char* arg) {
Ben Noordhuis2d82cdf2014-10-22 01:29:322903 const char* port = nullptr;
Zoran Tomicicd98ea702010-02-22 05:15:442904
Ben Noordhuisbd9c6662013-11-16 13:39:412905 if (!strcmp(arg, "--debug")) {
Miroslav Bajtoš43ec1b12013-05-02 06:34:222906 use_debug_agent = true;
Ben Noordhuisbd9c6662013-11-16 13:39:412907 } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
2908 use_debug_agent = true;
2909 port = arg + sizeof("--debug=") - 1;
2910 } else if (!strcmp(arg, "--debug-brk")) {
2911 use_debug_agent = true;
2912 debug_wait_connect = true;
2913 } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
2914 use_debug_agent = true;
2915 debug_wait_connect = true;
2916 port = arg + sizeof("--debug-brk=") - 1;
2917 } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
2918 port = arg + sizeof("--debug-port=") - 1;
2919 } else {
2920 return false;
2921 }
2922
Ben Noordhuis2d82cdf2014-10-22 01:29:322923 if (port != nullptr) {
Ben Noordhuisbd9c6662013-11-16 13:39:412924 debug_port = atoi(port);
2925 if (debug_port < 1024 || debug_port > 65535) {
2926 fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
2927 PrintHelp();
2928 exit(12);
Miroslav Bajtoš43ec1b12013-05-02 06:34:222929 }
Zoran Tomicicd98ea702010-02-22 05:15:442930 }
Zoran Tomicicd98ea702010-02-22 05:15:442931
Ben Noordhuisbd9c6662013-11-16 13:39:412932 return true;
Zoran Tomicicd98ea702010-02-22 05:15:442933}
2934
Ryand6c9d312009-09-11 14:02:292935static void PrintHelp() {
Jongyeol Choidaf95622015-01-16 14:45:372936 printf("Usage: iojs [options] [ -e script | script.js ] [arguments] \n"
2937 " iojs debug script.js [arguments] \n"
Ryan Dahl4fa712c2011-01-13 23:28:162938 "\n"
Ryan Dahl209b2192010-03-08 16:33:102939 "Options:\n"
Ben Noordhuis7d462472015-01-21 12:10:582940 " -v, --version print io.js version\n"
Steve Engledow292345f2011-07-05 11:07:082941 " -e, --eval script evaluate script\n"
Ben Noordhuiscb6d0842012-10-20 13:03:482942 " -p, --print evaluate script and print result\n"
Nathan Rajlichfeaa8a42012-03-21 07:05:252943 " -i, --interactive always enter the REPL even if stdin\n"
2944 " does not appear to be a terminal\n"
isaacs5b399292012-06-21 18:42:332945 " --no-deprecation silence deprecation warnings\n"
Trevor Norrisf10fd1d2014-05-07 21:47:572946 " --throw-deprecation throw an exception anytime a deprecated "
2947 "function is used\n"
isaacs5b399292012-06-21 18:42:332948 " --trace-deprecation show stack traces on deprecations\n"
Tom Hughes78da9cb2010-10-18 22:50:562949 " --v8-options print v8 command line options\n"
Tom Hughes78da9cb2010-10-18 22:50:562950 " --max-stack-size=val set max v8 stack size (bytes)\n"
Steven R. Loomisac2857b2014-09-05 05:03:242951#if defined(NODE_HAVE_I18N_SUPPORT)
2952 " --icu-data-dir=dir set ICU data load path to dir\n"
2953 " (overrides NODE_ICU_DATA)\n"
2954#if !defined(NODE_HAVE_SMALL_ICU)
2955 " Note: linked-in ICU data is\n"
2956 " present.\n"
2957#endif
2958#endif
Ryan Dahl209b2192010-03-08 16:33:102959 "\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112960 "Environment variables:\n"
2961#ifdef _WIN32
2962 "NODE_PATH ';'-separated list of directories\n"
2963#else
Tom Hughes78da9cb2010-10-18 22:50:562964 "NODE_PATH ':'-separated list of directories\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112965#endif
isaacsc050d0f2011-07-25 01:04:452966 " prefixed to the module search path.\n"
Tom Hughes78da9cb2010-10-18 22:50:562967 "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
2968 " global contexts.\n"
Ryan Dahl4fa712c2011-01-13 23:28:162969 "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
Steven R. Loomisac2857b2014-09-05 05:03:242970#if defined(NODE_HAVE_I18N_SUPPORT)
2971 "NODE_ICU_DATA Data path for ICU (Intl object) data\n"
2972#if !defined(NODE_HAVE_SMALL_ICU)
2973 " (will extend linked-in data)\n"
2974#endif
2975#endif
Ryan Dahl209b2192010-03-08 16:33:102976 "\n"
Shigeki Ohtsu8440cac2015-01-14 07:39:442977 "Documentation can be found at https://iojs.org/\n");
Ryan11df2522009-08-03 16:19:402978}
2979
Miroslav Bajtoš43ec1b12013-05-02 06:34:222980
Ben Noordhuis185c5152013-09-02 14:42:012981// Parse command line arguments.
2982//
2983// argv is modified in place. exec_argv and v8_argv are out arguments that
2984// ParseArgs() allocates memory for and stores a pointer to the output
2985// vector in. The caller should free them with delete[].
2986//
2987// On exit:
2988//
2989// * argv contains the arguments with node and V8 options filtered out.
2990// * exec_argv contains both node and V8 options and nothing else.
2991// * v8_argv contains argv[0] plus any V8 options
2992static void ParseArgs(int* argc,
2993 const char** argv,
2994 int* exec_argc,
2995 const char*** exec_argv,
2996 int* v8_argc,
2997 const char*** v8_argv) {
2998 const unsigned int nargs = static_cast<unsigned int>(*argc);
2999 const char** new_exec_argv = new const char*[nargs];
3000 const char** new_v8_argv = new const char*[nargs];
3001 const char** new_argv = new const char*[nargs];
Peter Griess78d33f42010-06-04 15:29:103002
Ben Noordhuis185c5152013-09-02 14:42:013003 for (unsigned int i = 0; i < nargs; ++i) {
Ben Noordhuis2d82cdf2014-10-22 01:29:323004 new_exec_argv[i] = nullptr;
3005 new_v8_argv[i] = nullptr;
3006 new_argv[i] = nullptr;
Ben Noordhuis185c5152013-09-02 14:42:013007 }
3008
3009 // exec_argv starts with the first option, the other two start with argv[0].
3010 unsigned int new_exec_argc = 0;
3011 unsigned int new_v8_argc = 1;
3012 unsigned int new_argc = 1;
3013 new_v8_argv[0] = argv[0];
3014 new_argv[0] = argv[0];
3015
3016 unsigned int index = 1;
3017 while (index < nargs && argv[index][0] == '-') {
3018 const char* const arg = argv[index];
3019 unsigned int args_consumed = 1;
3020
Ben Noordhuisbd9c6662013-11-16 13:39:413021 if (ParseDebugOpt(arg)) {
3022 // Done, consumed by ParseDebugOpt().
Ryan1910c112009-09-11 18:05:223023 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
Ryan11df2522009-08-03 16:19:403024 printf("%s\n", NODE_VERSION);
3025 exit(0);
3026 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
3027 PrintHelp();
3028 exit(0);
Ben Noordhuis185c5152013-09-02 14:42:013029 } else if (strcmp(arg, "--eval") == 0 ||
3030 strcmp(arg, "-e") == 0 ||
3031 strcmp(arg, "--print") == 0 ||
3032 strcmp(arg, "-pe") == 0 ||
Ben Noordhuisf03c3202012-09-03 14:42:183033 strcmp(arg, "-p") == 0) {
Ben Noordhuis2d82cdf2014-10-22 01:29:323034 bool is_eval = strchr(arg, 'e') != nullptr;
3035 bool is_print = strchr(arg, 'p') != nullptr;
Ben Noordhuis83b1dda2012-09-04 12:19:593036 print_eval = print_eval || is_print;
Ben Noordhuis185c5152013-09-02 14:42:013037 // --eval, -e and -pe always require an argument.
Ben Noordhuis83b1dda2012-09-04 12:19:593038 if (is_eval == true) {
Ben Noordhuis185c5152013-09-02 14:42:013039 args_consumed += 1;
3040 eval_string = argv[index + 1];
Ben Noordhuis2d82cdf2014-10-22 01:29:323041 if (eval_string == nullptr) {
Ben Noordhuis185c5152013-09-02 14:42:013042 fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
isaacsb30a03e2013-09-07 00:47:563043 exit(9);
Ben Noordhuis185c5152013-09-02 14:42:013044 }
Alexis Campailla14d6df82013-12-28 08:12:403045 } else if ((index + 1 < nargs) &&
Ben Noordhuis2d82cdf2014-10-22 01:29:323046 argv[index + 1] != nullptr &&
Alexis Campailla14d6df82013-12-28 08:12:403047 argv[index + 1][0] != '-') {
Ben Noordhuis185c5152013-09-02 14:42:013048 args_consumed += 1;
3049 eval_string = argv[index + 1];
3050 if (strncmp(eval_string, "\\-", 2) == 0) {
3051 // Starts with "\\-": escaped expression, drop the backslash.
3052 eval_string += 1;
3053 }
Ben Noordhuis83b1dda2012-09-04 12:19:593054 }
Nathan Rajlichfeaa8a42012-03-21 07:05:253055 } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
3056 force_repl = true;
isaacs5b399292012-06-21 18:42:333057 } else if (strcmp(arg, "--no-deprecation") == 0) {
isaacs5b399292012-06-21 18:42:333058 no_deprecation = true;
3059 } else if (strcmp(arg, "--trace-deprecation") == 0) {
isaacs5b399292012-06-21 18:42:333060 trace_deprecation = true;
isaacs5038f402013-03-06 01:46:373061 } else if (strcmp(arg, "--throw-deprecation") == 0) {
isaacs5038f402013-03-06 01:46:373062 throw_deprecation = true;
Ben Noordhuis185c5152013-09-02 14:42:013063 } else if (strcmp(arg, "--v8-options") == 0) {
3064 new_v8_argv[new_v8_argc] = "--help";
3065 new_v8_argc += 1;
Steven R. Loomisac2857b2014-09-05 05:03:243066#if defined(NODE_HAVE_I18N_SUPPORT)
3067 } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3068 icu_data_dir = arg + 15;
3069#endif
Ben Noordhuis185c5152013-09-02 14:42:013070 } else {
3071 // V8 option. Pass through as-is.
3072 new_v8_argv[new_v8_argc] = arg;
3073 new_v8_argc += 1;
Ryan11df2522009-08-03 16:19:403074 }
Ben Noordhuis185c5152013-09-02 14:42:013075
3076 memcpy(new_exec_argv + new_exec_argc,
3077 argv + index,
3078 args_consumed * sizeof(*argv));
3079
3080 new_exec_argc += args_consumed;
3081 index += args_consumed;
Ryan11df2522009-08-03 16:19:403082 }
Peter Griess78d33f42010-06-04 15:29:103083
Ben Noordhuis185c5152013-09-02 14:42:013084 // Copy remaining arguments.
3085 const unsigned int args_left = nargs - index;
3086 memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
3087 new_argc += args_left;
3088
3089 *exec_argc = new_exec_argc;
3090 *exec_argv = new_exec_argv;
3091 *v8_argc = new_v8_argc;
3092 *v8_argv = new_v8_argv;
3093
3094 // Copy new_argv over argv and update argc.
3095 memcpy(argv, new_argv, new_argc * sizeof(*argv));
3096 delete[] new_argv;
3097 *argc = static_cast<int>(new_argc);
Ryan11df2522009-08-03 16:19:403098}
3099
Bert Belder829735e2011-11-04 15:23:023100
Peter Rybin688859a2012-07-03 19:21:373101// Called from V8 Debug Agent TCP thread.
Fedor Indutny6a610a02014-10-04 14:44:393102static void DispatchMessagesDebugAgentCallback(Environment* env) {
3103 // TODO(indutny): move async handle to environment
Peter Rybin688859a2012-07-03 19:21:373104 uv_async_send(&dispatch_debug_messages_async);
3105}
3106
3107
Fedor Indutny6a610a02014-10-04 14:44:393108static void StartDebug(Environment* env, bool wait) {
3109 CHECK(!debugger_running);
3110
3111 env->debugger_agent()->set_dispatch_handler(
3112 DispatchMessagesDebugAgentCallback);
3113 debugger_running = env->debugger_agent()->Start(debug_port, wait);
Ben Noordhuisca363cf2013-10-15 21:32:183114 if (debugger_running == false) {
3115 fprintf(stderr, "Starting debugger on port %d failed\n", debug_port);
3116 fflush(stderr);
3117 return;
3118 }
Fedor Indutny6a610a02014-10-04 14:44:393119}
Ben Noordhuisca363cf2013-10-15 21:32:183120
Ben Noordhuisca363cf2013-10-15 21:32:183121
Fedor Indutny6a610a02014-10-04 14:44:393122// Called from the main thread.
3123static void EnableDebug(Environment* env) {
3124 CHECK(debugger_running);
Fedor Indutny8398bf92014-04-27 08:42:433125
Fedor Indutny6a610a02014-10-04 14:44:393126 // Send message to enable debug in workers
3127 HandleScope handle_scope(env->isolate());
3128
Fedor Indutnyce04c722014-03-13 16:38:143129 Local<Object> message = Object::New(env->isolate());
Ben Noordhuisca363cf2013-10-15 21:32:183130 message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
3131 FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
3132 Local<Value> argv[] = {
3133 FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
Ben Noordhuis756b6222013-08-10 22:26:113134 message
Ben Noordhuisf674b092013-08-07 19:50:413135 };
Ben Noordhuisca363cf2013-10-15 21:32:183136 MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv);
Fedor Indutny6a610a02014-10-04 14:44:393137
3138 // Enabled debugger, possibly making it wait on a semaphore
3139 env->debugger_agent()->Enable();
Miroslav Bajtoš43ec1b12013-05-02 06:34:223140}
3141
3142
Ben Noordhuisca363cf2013-10-15 21:32:183143// Called from the main thread.
Saúl Ibarra Corretgé42b93432014-03-12 23:08:293144static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {
Ben Noordhuisca363cf2013-10-15 21:32:183145 if (debugger_running == false) {
3146 fprintf(stderr, "Starting debugger agent.\n");
Fedor Indutny6a610a02014-10-04 14:44:393147
3148 Environment* env = Environment::GetCurrent(node_isolate);
3149 Context::Scope context_scope(env->context());
3150
3151 StartDebug(env, false);
3152 EnableDebug(env);
Ben Noordhuis756b6222013-08-10 22:26:113153 }
Ben Noordhuisca363cf2013-10-15 21:32:183154 Isolate::Scope isolate_scope(node_isolate);
3155 v8::Debug::ProcessDebugMessages();
Ryan Dahl2a7e7b12010-12-18 19:17:293156}
3157
3158
Fedor Indutny82d0ac72011-09-24 13:51:593159#ifdef __POSIX__
Ben Noordhuisca363cf2013-10-15 21:32:183160static void EnableDebugSignalHandler(int signo) {
3161 // Call only async signal-safe functions here!
3162 v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3163 uv_async_send(&dispatch_debug_messages_async);
Ryan Dahl2a7e7b12010-12-18 19:17:293164}
3165
3166
Geir Haugec61b0e92014-03-31 07:52:033167static void RegisterSignalHandler(int signal,
3168 void (*handler)(int signal),
3169 bool reset_handler = false) {
Tom Hughesf61b1102010-10-12 21:01:583170 struct sigaction sa;
Tom Hughesf61b1102010-10-12 21:01:583171 memset(&sa, 0, sizeof(sa));
3172 sa.sa_handler = handler;
Geir Haugec61b0e92014-03-31 07:52:033173 sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
Tom Hughesf61b1102010-10-12 21:01:583174 sigfillset(&sa.sa_mask);
Ben Noordhuis2d82cdf2014-10-22 01:29:323175 CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
Bert Belder829735e2011-11-04 15:23:023176}
3177
3178
Ben Noordhuis110a9cd2013-07-03 02:23:443179void DebugProcess(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:553180 Environment* env = Environment::GetCurrent(args);
Bert Belder829735e2011-11-04 15:23:023181
3182 if (args.Length() != 1) {
Fedor Indutny75adde02014-02-21 13:02:423183 return env->ThrowError("Invalid number of arguments.");
Bert Belder829735e2011-11-04 15:23:023184 }
3185
3186 pid_t pid;
3187 int r;
3188
3189 pid = args[0]->IntegerValue();
3190 r = kill(pid, SIGUSR1);
3191 if (r != 0) {
Fedor Indutny75adde02014-02-21 13:02:423192 return env->ThrowErrnoException(errno, "kill");
Bert Belder829735e2011-11-04 15:23:023193 }
Tom Hughesf61b1102010-10-12 21:01:583194}
Ben Noordhuisca363cf2013-10-15 21:32:183195
3196
3197static int RegisterDebugSignalHandler() {
3198 // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3199 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
Ben Noordhuis63ae1d22015-01-26 22:26:333200 // Unblock SIGUSR1. A pending SIGUSR1 signal will now be delivered.
3201 sigset_t sigmask;
3202 sigemptyset(&sigmask);
3203 sigaddset(&sigmask, SIGUSR1);
3204 CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr));
Ben Noordhuisca363cf2013-10-15 21:32:183205 return 0;
3206}
Fedor Indutny8e29ce92013-07-31 18:07:293207#endif // __POSIX__
Tom Hughesf61b1102010-10-12 21:01:583208
3209
Bert Belder829735e2011-11-04 15:23:023210#ifdef _WIN32
3211DWORD WINAPI EnableDebugThreadProc(void* arg) {
Ben Noordhuisca363cf2013-10-15 21:32:183212 v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
3213 uv_async_send(&dispatch_debug_messages_async);
Bert Belder829735e2011-11-04 15:23:023214 return 0;
3215}
3216
3217
Bert Belder8f2694b2012-02-16 21:19:483218static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
3219 size_t buf_len) {
3220 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
Bert Belder829735e2011-11-04 15:23:023221}
3222
3223
3224static int RegisterDebugSignalHandler() {
Bert Belder8f2694b2012-02-16 21:19:483225 wchar_t mapping_name[32];
Bert Belder829735e2011-11-04 15:23:023226 HANDLE mapping_handle;
3227 DWORD pid;
3228 LPTHREAD_START_ROUTINE* handler;
3229
3230 pid = GetCurrentProcessId();
3231
3232 if (GetDebugSignalHandlerMappingName(pid,
3233 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:483234 ARRAY_SIZE(mapping_name)) < 0) {
Bert Belder829735e2011-11-04 15:23:023235 return -1;
3236 }
3237
Bert Belder8f2694b2012-02-16 21:19:483238 mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
Ben Noordhuis2d82cdf2014-10-22 01:29:323239 nullptr,
Bert Belder829735e2011-11-04 15:23:023240 PAGE_READWRITE,
3241 0,
3242 sizeof *handler,
3243 mapping_name);
Ben Noordhuis2d82cdf2014-10-22 01:29:323244 if (mapping_handle == nullptr) {
Bert Belder829735e2011-11-04 15:23:023245 return -1;
3246 }
3247
Bert Belder8f2694b2012-02-16 21:19:483248 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3249 MapViewOfFile(mapping_handle,
3250 FILE_MAP_ALL_ACCESS,
3251 0,
3252 0,
3253 sizeof *handler));
Ben Noordhuis2d82cdf2014-10-22 01:29:323254 if (handler == nullptr) {
Bert Belder829735e2011-11-04 15:23:023255 CloseHandle(mapping_handle);
3256 return -1;
3257 }
3258
3259 *handler = EnableDebugThreadProc;
3260
Fedor Indutny8e29ce92013-07-31 18:07:293261 UnmapViewOfFile(static_cast<void*>(handler));
Bert Belder829735e2011-11-04 15:23:023262
3263 return 0;
3264}
3265
3266
Ben Noordhuis110a9cd2013-07-03 02:23:443267static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
Ben Noordhuisd3c317e2014-10-13 13:19:553268 Environment* env = Environment::GetCurrent(args);
Alexis Campailla440b9e22014-02-24 18:55:273269 Isolate* isolate = args.GetIsolate();
Bert Belder829735e2011-11-04 15:23:023270 DWORD pid;
Ben Noordhuis2d82cdf2014-10-22 01:29:323271 HANDLE process = nullptr;
3272 HANDLE thread = nullptr;
3273 HANDLE mapping = nullptr;
Bert Belder8f2694b2012-02-16 21:19:483274 wchar_t mapping_name[32];
Ben Noordhuis2d82cdf2014-10-22 01:29:323275 LPTHREAD_START_ROUTINE* handler = nullptr;
Bert Belder829735e2011-11-04 15:23:023276
3277 if (args.Length() != 1) {
Fedor Indutny75adde02014-02-21 13:02:423278 env->ThrowError("Invalid number of arguments.");
Bert Belder829735e2011-11-04 15:23:023279 goto out;
3280 }
3281
3282 pid = (DWORD) args[0]->IntegerValue();
3283
Bert Belder68db2062012-02-03 14:37:463284 process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
Bert Belder829735e2011-11-04 15:23:023285 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
3286 PROCESS_VM_READ,
3287 FALSE,
3288 pid);
Ben Noordhuis2d82cdf2014-10-22 01:29:323289 if (process == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273290 isolate->ThrowException(
3291 WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
Bert Belder829735e2011-11-04 15:23:023292 goto out;
3293 }
3294
3295 if (GetDebugSignalHandlerMappingName(pid,
3296 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:483297 ARRAY_SIZE(mapping_name)) < 0) {
Fedor Indutny75adde02014-02-21 13:02:423298 env->ThrowErrnoException(errno, "sprintf");
Bert Belder829735e2011-11-04 15:23:023299 goto out;
3300 }
3301
Bert Belder8f2694b2012-02-16 21:19:483302 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
Ben Noordhuis2d82cdf2014-10-22 01:29:323303 if (mapping == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273304 isolate->ThrowException(WinapiErrnoException(isolate,
Fedor Indutny75adde02014-02-21 13:02:423305 GetLastError(),
3306 "OpenFileMappingW"));
Bert Belder829735e2011-11-04 15:23:023307 goto out;
3308 }
3309
Bert Belder8f2694b2012-02-16 21:19:483310 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3311 MapViewOfFile(mapping,
3312 FILE_MAP_READ,
3313 0,
3314 0,
3315 sizeof *handler));
Ben Noordhuis2d82cdf2014-10-22 01:29:323316 if (handler == nullptr || *handler == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273317 isolate->ThrowException(
3318 WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
Bert Belder829735e2011-11-04 15:23:023319 goto out;
3320 }
3321
Bert Belder68db2062012-02-03 14:37:463322 thread = CreateRemoteThread(process,
Ben Noordhuis2d82cdf2014-10-22 01:29:323323 nullptr,
Bert Belder829735e2011-11-04 15:23:023324 0,
3325 *handler,
Ben Noordhuis2d82cdf2014-10-22 01:29:323326 nullptr,
Bert Belder829735e2011-11-04 15:23:023327 0,
Ben Noordhuis2d82cdf2014-10-22 01:29:323328 nullptr);
3329 if (thread == nullptr) {
Alexis Campailla440b9e22014-02-24 18:55:273330 isolate->ThrowException(WinapiErrnoException(isolate,
3331 GetLastError(),
3332 "CreateRemoteThread"));
Bert Belder829735e2011-11-04 15:23:023333 goto out;
3334 }
3335
3336 // Wait for the thread to terminate
3337 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
Alexis Campailla440b9e22014-02-24 18:55:273338 isolate->ThrowException(WinapiErrnoException(isolate,
3339 GetLastError(),
3340 "WaitForSingleObject"));
Bert Belder829735e2011-11-04 15:23:023341 goto out;
3342 }
3343
3344 out:
Ben Noordhuis2d82cdf2014-10-22 01:29:323345 if (process != nullptr)
Fedor Indutny8e29ce92013-07-31 18:07:293346 CloseHandle(process);
Ben Noordhuis2d82cdf2014-10-22 01:29:323347 if (thread != nullptr)
Bert Belder829735e2011-11-04 15:23:023348 CloseHandle(thread);
Ben Noordhuis2d82cdf2014-10-22 01:29:323349 if (handler != nullptr)
Bert Belder829735e2011-11-04 15:23:023350 UnmapViewOfFile(handler);
Ben Noordhuis2d82cdf2014-10-22 01:29:323351 if (mapping != nullptr)
Bert Belder829735e2011-11-04 15:23:023352 CloseHandle(mapping);
Bert Belder829735e2011-11-04 15:23:023353}
Fedor Indutny8e29ce92013-07-31 18:07:293354#endif // _WIN32
Bert Belder829735e2011-11-04 15:23:023355
3356
Ben Noordhuis110a9cd2013-07-03 02:23:443357static void DebugPause(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny75adde02014-02-21 13:02:423358 v8::Debug::DebugBreak(args.GetIsolate());
Fedor Indutnyb0388cc2011-12-10 16:52:073359}
3360
3361
Ben Noordhuis110a9cd2013-07-03 02:23:443362static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
Fedor Indutny3f43b1c2012-02-12 15:53:433363 if (debugger_running) {
Ben Noordhuisd3c317e2014-10-13 13:19:553364 Environment* env = Environment::GetCurrent(args);
Fedor Indutny6a610a02014-10-04 14:44:393365 env->debugger_agent()->Stop();
Fedor Indutny3f43b1c2012-02-12 15:53:433366 debugger_running = false;
3367 }
Fedor Indutny3f43b1c2012-02-12 15:53:433368}
3369
3370
Ben Noordhuis5756f922015-01-26 22:15:203371inline void PlatformInit() {
3372#ifdef __POSIX__
Ben Noordhuis63ae1d22015-01-26 22:26:333373 sigset_t sigmask;
3374 sigemptyset(&sigmask);
3375 sigaddset(&sigmask, SIGUSR1);
3376 CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, nullptr));
Ben Noordhuisdd47a8c2015-01-26 23:07:343377
3378 // Restore signal dispositions, the parent process may have changed them.
3379 struct sigaction act;
3380 memset(&act, 0, sizeof(act));
3381
3382 // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
3383 // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
3384 // Counting up to SIGRTMIN doesn't work for the same reason.
3385 for (unsigned nr = 1; nr < 32; nr += 1) {
3386 if (nr == SIGKILL || nr == SIGSTOP)
3387 continue;
3388 act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
3389 CHECK_EQ(0, sigaction(nr, &act, nullptr));
3390 }
3391
Ben Noordhuis63ae1d22015-01-26 22:26:333392 RegisterSignalHandler(SIGINT, SignalExit, true);
3393 RegisterSignalHandler(SIGTERM, SignalExit, true);
Ben Noordhuisdd47a8c2015-01-26 23:07:343394
Ben Noordhuis96ffcb92015-01-29 17:48:303395 // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the
3396 // performance penalty of frequent EINTR wakeups when the profiler is running.
3397 uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
3398
Ben Noordhuis5756f922015-01-26 22:15:203399 // Raise the open file descriptor limit.
3400 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 }
Ben Noordhuis5756f922015-01-26 22:15:203419#endif // __POSIX__
3420}
3421
3422
Ben Noordhuis185c5152013-09-02 14:42:013423void Init(int* argc,
3424 const char** argv,
3425 int* exec_argc,
3426 const char*** exec_argv) {
Ben Noordhuis74a82152012-02-03 15:32:003427 // Initialize prog_start_time to get relative uptime.
Rasmus Christian Pedersen734fb492014-09-18 12:10:533428 prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
Ben Noordhuis74a82152012-02-03 15:32:003429
Bert Belder09be3602012-06-13 23:28:513430 // Make inherited handles noninheritable.
3431 uv_disable_stdio_inheritance();
3432
Miroslav Bajtošfbf46412013-05-02 14:42:493433 // init async debug messages dispatching
Ben Noordhuis756b6222013-08-10 22:26:113434 // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
Miroslav Bajtošfbf46412013-05-02 14:42:493435 uv_async_init(uv_default_loop(),
3436 &dispatch_debug_messages_async,
3437 DispatchDebugMessagesAsyncCallback);
3438 uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
3439
Ben Noordhuis490d5ab2014-03-31 12:22:493440#if defined(NODE_V8_OPTIONS)
3441 // Should come before the call to V8::SetFlagsFromCommandLine()
3442 // so the user can disable a flag --foo at run-time by passing
3443 // --no_foo from the command line.
3444 V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
3445#endif
Fedor Indutnyb55c9d62014-03-26 20:30:493446
Ryan Dahl38814552009-10-09 15:15:473447 // Parse a few arguments which are specific to Node.
Ben Noordhuis185c5152013-09-02 14:42:013448 int v8_argc;
3449 const char** v8_argv;
3450 ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
Danny Coatesdc8c0792010-08-01 22:46:483451
Ben Noordhuis9566fe82013-10-03 08:45:323452 // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
3453 // manually? That would give us a little more control over its runtime
3454 // behavior but it could also interfere with the user's intentions in ways
3455 // we fail to anticipate. Dillema.
3456 for (int i = 1; i < v8_argc; ++i) {
3457 if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
3458 v8_is_profiling = true;
3459 break;
3460 }
3461 }
3462
Steven R. Loomisac2857b2014-09-05 05:03:243463#if defined(NODE_HAVE_I18N_SUPPORT)
Ben Noordhuis2d82cdf2014-10-22 01:29:323464 if (icu_data_dir == nullptr) {
Steven R. Loomisac2857b2014-09-05 05:03:243465 // if the parameter isn't given, use the env variable.
Ben Noordhuis8f6c5872014-10-11 19:48:253466 icu_data_dir = secure_getenv("NODE_ICU_DATA");
Steven R. Loomisac2857b2014-09-05 05:03:243467 }
3468 // Initialize ICU.
Ben Noordhuis2d82cdf2014-10-22 01:29:323469 // If icu_data_dir is nullptr here, it will load the 'minimal' data.
Steven R. Loomisac2857b2014-09-05 05:03:243470 if (!i18n::InitializeICUDirectory(icu_data_dir)) {
Ben Noordhuis2d82cdf2014-10-22 01:29:323471 FatalError(nullptr, "Could not initialize ICU "
Steven R. Loomisac2857b2014-09-05 05:03:243472 "(check NODE_ICU_DATA or --icu-data-dir parameters)");
3473 }
3474#endif
Ben Noordhuis185c5152013-09-02 14:42:013475 // The const_cast doesn't violate conceptual const-ness. V8 doesn't modify
3476 // the argv array or the elements it points to.
3477 V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
3478
3479 // Anything that's still in v8_argv is not a V8 or a node option.
3480 for (int i = 1; i < v8_argc; i++) {
3481 fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
3482 }
3483 delete[] v8_argv;
Ben Noordhuis2d82cdf2014-10-22 01:29:323484 v8_argv = nullptr;
Ben Noordhuis185c5152013-09-02 14:42:013485
3486 if (v8_argc > 1) {
isaacsb30a03e2013-09-07 00:47:563487 exit(9);
Ryan Dahladec5442010-08-04 17:38:193488 }
Tom Hughes78da9cb2010-10-18 22:50:563489
Ben Noordhuis185c5152013-09-02 14:42:013490 if (debug_wait_connect) {
3491 const char expose_debug_as[] = "--expose_debug_as=v8debug";
3492 V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
3493 }
Ryan23376302009-09-10 10:34:293494
Ben Noordhuis0693d222013-06-29 06:16:253495 V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton);
3496
Fedor Indutny6a610a02014-10-04 14:44:393497 if (!use_debug_agent) {
Ben Noordhuis74a82152012-02-03 15:32:003498 RegisterDebugSignalHandler();
Ben Noordhuis74a82152012-02-03 15:32:003499 }
Cheng Zhao22e1aea2015-01-12 21:31:253500
3501 // We should set node_is_initialized here instead of in node::Start,
3502 // otherwise embedders using node::Init to initialize everything will not be
3503 // able to set it and native modules will not load for them.
3504 node_is_initialized = true;
Ben Noordhuis5866f1a2011-12-09 18:02:333505}
Ben Noordhuis356992f2011-11-22 16:10:093506
Ben Noordhuis5866f1a2011-12-09 18:02:333507
Ben Noordhuise4a8d262012-04-21 05:13:253508struct AtExitCallback {
3509 AtExitCallback* next_;
3510 void (*cb_)(void* arg);
3511 void* arg_;
3512};
3513
3514static AtExitCallback* at_exit_functions_;
3515
3516
Ben Noordhuis756b6222013-08-10 22:26:113517// TODO(bnoordhuis) Turn into per-context event.
3518void RunAtExit(Environment* env) {
Ben Noordhuise4a8d262012-04-21 05:13:253519 AtExitCallback* p = at_exit_functions_;
Ben Noordhuis2d82cdf2014-10-22 01:29:323520 at_exit_functions_ = nullptr;
Ben Noordhuise4a8d262012-04-21 05:13:253521
3522 while (p) {
3523 AtExitCallback* q = p->next_;
3524 p->cb_(p->arg_);
3525 delete p;
3526 p = q;
3527 }
3528}
3529
3530
3531void AtExit(void (*cb)(void* arg), void* arg) {
3532 AtExitCallback* p = new AtExitCallback;
3533 p->cb_ = cb;
3534 p->arg_ = arg;
3535 p->next_ = at_exit_functions_;
3536 at_exit_functions_ = p;
3537}
3538
3539
Ben Noordhuisa2eeb432013-10-07 13:39:393540void EmitBeforeExit(Environment* env) {
3541 Context::Scope context_scope(env->context());
3542 HandleScope handle_scope(env->isolate());
3543 Local<Object> process_object = env->process_object();
3544 Local<String> exit_code = FIXED_ONE_BYTE_STRING(env->isolate(), "exitCode");
3545 Local<Value> args[] = {
3546 FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
Trevor Norrisd5533862015-01-07 21:29:583547 process_object->Get(exit_code)->ToInteger(env->isolate())
Ben Noordhuisa2eeb432013-10-07 13:39:393548 };
3549 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3550}
3551
3552
Fedor Indutnye57ab7b2014-01-18 22:49:333553int EmitExit(Environment* env) {
Ben Noordhuis5866f1a2011-12-09 18:02:333554 // process.emit('exit')
Ben Noordhuis756b6222013-08-10 22:26:113555 HandleScope handle_scope(env->isolate());
Ben Noordhuis27f115d2013-11-11 09:53:003556 Context::Scope context_scope(env->context());
Ben Noordhuis756b6222013-08-10 22:26:113557 Local<Object> process_object = env->process_object();
Fedor Indutny75adde02014-02-21 13:02:423558 process_object->Set(env->exiting_string(), True(env->isolate()));
isaacsa5dba822013-09-06 23:46:353559
Fedor Indutny75adde02014-02-21 13:02:423560 Handle<String> exitCode = env->exit_code_string();
Rasmus Christian Pedersen734fb492014-09-18 12:10:533561 int code = process_object->Get(exitCode)->Int32Value();
isaacsa5dba822013-09-06 23:46:353562
Ben Noordhuisf674b092013-08-07 19:50:413563 Local<Value> args[] = {
Fedor Indutny75adde02014-02-21 13:02:423564 env->exit_string(),
Fedor Indutnyce04c722014-03-13 16:38:143565 Integer::New(env->isolate(), code)
Ben Noordhuisf674b092013-08-07 19:50:413566 };
isaacsa5dba822013-09-06 23:46:353567
Ben Noordhuis756b6222013-08-10 22:26:113568 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
Fedor Indutnyc0d81f92014-02-09 10:40:573569
3570 // Reload exit code, it may be changed by `emit('exit')`
Rasmus Christian Pedersen734fb492014-09-18 12:10:533571 return process_object->Get(exitCode)->Int32Value();
Ben Noordhuis756b6222013-08-10 22:26:113572}
3573
3574
Fedor Indutny6a610a02014-10-04 14:44:393575// Just a convenience method
Ben Noordhuis756b6222013-08-10 22:26:113576Environment* CreateEnvironment(Isolate* isolate,
Dean McNameeda30c002014-07-09 11:36:503577 Handle<Context> context,
Ben Noordhuis756b6222013-08-10 22:26:113578 int argc,
3579 const char* const* argv,
3580 int exec_argc,
3581 const char* const* exec_argv) {
Fedor Indutny6a610a02014-10-04 14:44:393582 Environment* env;
3583 Context::Scope context_scope(context);
3584
3585 env = CreateEnvironment(isolate,
3586 uv_default_loop(),
3587 context,
3588 argc,
3589 argv,
3590 exec_argc,
3591 exec_argv);
3592
3593 LoadEnvironment(env);
3594
3595 return env;
3596}
3597
3598
3599static void HandleCloseCb(uv_handle_t* handle) {
3600 Environment* env = reinterpret_cast<Environment*>(handle->data);
3601 env->FinishHandleCleanup(handle);
3602}
3603
3604
3605static void HandleCleanup(Environment* env,
3606 uv_handle_t* handle,
3607 void* arg) {
3608 handle->data = env;
3609 uv_close(handle, HandleCloseCb);
3610}
3611
3612
3613Environment* CreateEnvironment(Isolate* isolate,
3614 uv_loop_t* loop,
3615 Handle<Context> context,
3616 int argc,
3617 const char* const* argv,
3618 int exec_argc,
3619 const char* const* exec_argv) {
Ben Noordhuis756b6222013-08-10 22:26:113620 HandleScope handle_scope(isolate);
3621
Ben Noordhuis756b6222013-08-10 22:26:113622 Context::Scope context_scope(context);
Fedor Indutny6a610a02014-10-04 14:44:393623 Environment* env = Environment::New(context, loop);
Ben Noordhuis756b6222013-08-10 22:26:113624
Vladimir Kurchatkin8dc6be12014-09-22 16:19:503625 isolate->SetAutorunMicrotasks(false);
3626
Ben Noordhuis756b6222013-08-10 22:26:113627 uv_check_init(env->event_loop(), env->immediate_check_handle());
3628 uv_unref(
3629 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
Fedor Indutny6a610a02014-10-04 14:44:393630
Ben Noordhuis756b6222013-08-10 22:26:113631 uv_idle_init(env->event_loop(), env->immediate_idle_handle());
3632
Ben Noordhuis57231d52013-10-02 04:37:443633 // Inform V8's CPU profiler when we're idle. The profiler is sampling-based
3634 // but not all samples are created equal; mark the wall clock time spent in
3635 // epoll_wait() and friends so profiling tools can filter it out. The samples
3636 // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
Ben Noordhuis57231d52013-10-02 04:37:443637 // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
3638 // probably fortify in the API contract, namely that the last started prepare
3639 // or check watcher runs first. It's not 100% foolproof; if an add-on starts
3640 // a prepare or check watcher after us, any samples attributed to its callback
3641 // will be recorded with state=IDLE.
3642 uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
Ben Noordhuis58729f12013-10-03 17:27:513643 uv_check_init(env->event_loop(), env->idle_check_handle());
Ben Noordhuis57231d52013-10-02 04:37:443644 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
Ben Noordhuis57231d52013-10-02 04:37:443645 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
3646
Fedor Indutny6a610a02014-10-04 14:44:393647 // Register handle cleanups
3648 env->RegisterHandleCleanup(
3649 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()),
3650 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323651 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393652 env->RegisterHandleCleanup(
3653 reinterpret_cast<uv_handle_t*>(env->immediate_idle_handle()),
3654 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323655 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393656 env->RegisterHandleCleanup(
3657 reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()),
3658 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323659 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393660 env->RegisterHandleCleanup(
3661 reinterpret_cast<uv_handle_t*>(env->idle_check_handle()),
3662 HandleCleanup,
Ben Noordhuis2d82cdf2014-10-22 01:29:323663 nullptr);
Fedor Indutny6a610a02014-10-04 14:44:393664
Ben Noordhuis9566fe82013-10-03 08:45:323665 if (v8_is_profiling) {
Ben Noordhuis58729f12013-10-03 17:27:513666 StartProfilerIdleNotifier(env);
Ben Noordhuis9566fe82013-10-03 08:45:323667 }
3668
Fedor Indutnyce04c722014-03-13 16:38:143669 Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
Ben Noordhuisf6496262013-10-03 09:03:463670 process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
3671
3672 Local<Object> process_object = process_template->GetFunction()->NewInstance();
3673 env->set_process_object(process_object);
3674
3675 SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
Ben Noordhuisf6496262013-10-03 09:03:463676
Ben Noordhuis756b6222013-08-10 22:26:113677 return env;
Ben Noordhuis5866f1a2011-12-09 18:02:333678}
3679
Micheil Smith19fd5302012-03-05 17:53:153680
Ben Noordhuis185c5152013-09-02 14:42:013681int Start(int argc, char** argv) {
Ben Noordhuis5756f922015-01-26 22:15:203682 PlatformInit();
3683
Ben Noordhuis8f6c5872014-10-11 19:48:253684 const char* replaceInvalid = secure_getenv("NODE_INVALID_UTF8");
Felix Geisendörfer0da4c672014-01-20 08:47:193685
Ben Noordhuis2d82cdf2014-10-22 01:29:323686 if (replaceInvalid == nullptr)
Felix Geisendörfer0da4c672014-01-20 08:47:193687 WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8;
3688
Ben Noordhuis5fdff382014-10-11 14:52:073689 CHECK_GT(argc, 0);
Micheil Smith19fd5302012-03-05 17:53:153690
Ben Noordhuis185c5152013-09-02 14:42:013691 // Hack around with the argv pointer. Used for process.title = "blah".
Ben Noordhuis1a979982012-03-15 22:10:323692 argv = uv_setup_args(argc, argv);
3693
Ben Noordhuis185c5152013-09-02 14:42:013694 // This needs to run *before* V8::Initialize(). The const_cast is not
3695 // optional, in case you're wondering.
3696 int exec_argc;
3697 const char** exec_argv;
3698 Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
Ben Noordhuis5866f1a2011-12-09 18:02:333699
Ben Noordhuis7ac23912013-09-20 20:01:493700#if HAVE_OPENSSL
3701 // V8 on Windows doesn't have a good source of entropy. Seed it from
3702 // OpenSSL's pool.
3703 V8::SetEntropySource(crypto::EntropySource);
3704#endif
3705
Fedor Indutny50839a02014-10-10 22:17:033706 V8::InitializePlatform(new Platform(4));
3707
Fedor Indutnye57ab7b2014-01-18 22:49:333708 int code;
Ben Noordhuis75ea5662013-09-23 12:27:263709 V8::Initialize();
Fedor Indutny50839a02014-10-10 22:17:033710
3711 // Fetch a reference to the main isolate, so we have a reference to it
3712 // even when we need it to access it from another (debugger) thread.
3713 node_isolate = Isolate::New();
Marcel Laverdetc33d3172012-05-04 22:29:423714 {
Trevor Norris0bba5902013-03-18 20:54:003715 Locker locker(node_isolate);
Ben Noordhuis437c2f42014-08-19 17:28:063716 Isolate::Scope isolate_scope(node_isolate);
Dean McNameeda30c002014-07-09 11:36:503717 HandleScope handle_scope(node_isolate);
3718 Local<Context> context = Context::New(node_isolate);
3719 Environment* env = CreateEnvironment(
Fedor Indutny6a610a02014-10-04 14:44:393720 node_isolate,
3721 uv_default_loop(),
3722 context,
3723 argc,
3724 argv,
3725 exec_argc,
3726 exec_argv);
3727 Context::Scope context_scope(context);
Fedor Indutny5596f932014-02-28 13:25:283728
Fedor Indutny6a610a02014-10-04 14:44:393729 // Start debug agent when argv has --debug
3730 if (use_debug_agent)
3731 StartDebug(env, debug_wait_connect);
3732
3733 LoadEnvironment(env);
3734
3735 // Enable debugger
3736 if (use_debug_agent)
3737 EnableDebug(env);
3738
3739 bool more;
3740 do {
3741 more = uv_run(env->event_loop(), UV_RUN_ONCE);
3742 if (more == false) {
3743 EmitBeforeExit(env);
3744
3745 // Emit `beforeExit` if the loop became alive either after emitting
3746 // event, or after running some callbacks.
3747 more = uv_loop_alive(env->event_loop());
3748 if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
3749 more = true;
3750 }
3751 } while (more == true);
3752 code = EmitExit(env);
3753 RunAtExit(env);
3754
Ben Noordhuis756b6222013-08-10 22:26:113755 env->Dispose();
Ben Noordhuis2d82cdf2014-10-22 01:29:323756 env = nullptr;
Marcel Laverdetc33d3172012-05-04 22:29:423757 }
3758
Ben Noordhuis2d82cdf2014-10-22 01:29:323759 CHECK_NE(node_isolate, nullptr);
Ben Noordhuis6f952842014-05-22 23:08:273760 node_isolate->Dispose();
Ben Noordhuis2d82cdf2014-10-22 01:29:323761 node_isolate = nullptr;
Ryan27b268b2009-06-17 13:05:443762 V8::Dispose();
Igor Zinkovskya58b6432011-07-07 20:54:303763
Ben Noordhuis185c5152013-09-02 14:42:013764 delete[] exec_argv;
Ben Noordhuis2d82cdf2014-10-22 01:29:323765 exec_argv = nullptr;
Micheil Smith19fd5302012-03-05 17:53:153766
Fedor Indutnye57ab7b2014-01-18 22:49:333767 return code;
Ryan19478ed2009-03-03 00:56:153768}
Ryan Dahl124fbed2010-09-19 20:13:573769
3770
3771} // namespace node