Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Revert support for isolates.

It was decided that the performance benefits that isolates offer (faster spin-up
times for worker processes, faster inter-worker communication, possibly a lower
memory footprint) are not actual bottlenecks for most people and do not outweigh
the potential stability issues and intrusive changes to the code base that
first-class support for isolates requires.

Hence, this commit backs out all isolates-related changes.

Good bye, isolates. We hardly knew ye.
  • Loading branch information...
commit 74a8215a8699f89ee4b82ca616a4eafa3b11203b 1 parent a9723df
@bnoordhuis bnoordhuis authored
Showing with 413 additions and 2,257 deletions.
  1. +0 −6 configure
  2. +14 −50 lib/_debugger.js
  3. +4 −65 lib/child_process.js
  4. +0 −12 node.gyp
  5. +9 −10 src/cares_wrap.cc
  6. +4 −5 src/fs_event_wrap.cc
  7. +2 −3 src/handle_wrap.cc
  8. +0 −109 src/ngx-queue.h
  9. +129 −151 src/node.cc
  10. +0 −4 src/node.h
  11. +0 −32 src/node.js
  12. +33 −35 src/node_buffer.cc
  13. +1 −0  src/node_buffer.h
  14. +20 −27 src/node_crypto.cc
  15. +0 −4 src/node_extensions.h
  16. +25 −29 src/node_file.cc
  17. +51 −47 src/node_http_parser.cc
  18. +0 −15 src/node_internals.h
  19. +0 −815 src/node_isolate.cc
  20. +0 −185 src/node_isolate.h
  21. +29 −22 src/node_script.cc
  22. +10 −11 src/node_signal_watcher.cc
  23. +0 −48 src/node_vars.cc
  24. +0 −197 src/node_vars.h
  25. +3 −5 src/node_zlib.cc
  26. +4 −5 src/pipe_wrap.cc
  27. +3 −4 src/process_wrap.cc
  28. +18 −23 src/stream_wrap.cc
  29. +19 −23 src/tcp_wrap.cc
  30. +9 −10 src/timer_wrap.cc
  31. +3 −4 src/tty_wrap.cc
  32. +8 −9 src/udp_wrap.cc
  33. +0 −55 test/addons/shared-buffer/binding.cc
  34. +0 −8 test/addons/shared-buffer/binding.gyp
  35. +0 −19 test/addons/shared-buffer/test.js
  36. +1 −7 test/simple/test-child-process-fork.js
  37. +1 −5 test/simple/test-child-process-fork2.js
  38. +1 −5 test/simple/test-child-process-fork3.js
  39. +6 −13 test/simple/test-debugger-repl-utf8.js
  40. +6 −13 test/simple/test-debugger-repl.js
  41. +0 −68 test/simple/test-isolates-ping-pong.js
  42. +0 −60 test/simple/test-isolates0.js
  43. +0 −13 test/simple/test-isolates1.js
  44. +0 −13 test/simple/test-isolates2.js
  45. +0 −13 test/simple/test-isolates3.js
View
6 configure
@@ -32,11 +32,6 @@ parser.add_option("--without-waf",
dest="without_waf",
help="Don\'t install node-waf")
-parser.add_option("--without-isolates",
- action="store_true",
- dest="without_isolates",
- help="Build without isolates (no threads, single loop) [Default: False]")
-
parser.add_option("--without-ssl",
action="store_true",
dest="without_ssl",
@@ -172,7 +167,6 @@ def target_arch():
def configure_node(o):
# TODO add gdb
- o['variables']['node_use_isolates'] = b(not options.without_isolates)
o['variables']['node_prefix'] = options.prefix if options.prefix else ''
o['variables']['node_use_dtrace'] = b(options.with_dtrace)
o['variables']['node_install_npm'] = b(not options.without_npm)
View
64 lib/_debugger.js
@@ -25,7 +25,7 @@ var util = require('util'),
vm = require('vm'),
repl = require('repl'),
inherits = util.inherits,
- fork = require('child_process').fork;
+ spawn = require('child_process').spawn;
exports.start = function(argv, stdin, stdout) {
argv || (argv = process.argv.slice(2));
@@ -39,7 +39,7 @@ exports.start = function(argv, stdin, stdout) {
stdin = stdin || process.openStdin();
stdout = stdout || process.stdout;
- var args = argv,
+ var args = ['--debug-brk'].concat(argv),
interface = new Interface(stdin, stdout, args);
stdin.resume();
@@ -169,8 +169,6 @@ function Client() {
this.scripts = {};
this.breakpoints = [];
- this.isolates = process.features.isolates;
-
// Note that 'Protocol' requires strings instead of Buffers.
socket.setEncoding('utf8');
socket.on('data', function(d) {
@@ -1597,51 +1595,20 @@ Interface.prototype.trySpawn = function(cb) {
}
}
- var client = self.client = new Client(),
- connectionAttempts = 0;
-
if (!this.child) {
- if (client.isolates) {
- this.child = fork(this.args.shift(), this.args, {
- thread: true,
- debug: function(d) {
- d.onmessage = function(event) {
- client._onResponse({
- headers: {},
- body: JSON.parse(event)
- });
- };
-
- // Monkey patch client to send requests directly to debugger
- client.req = function(req, cb) {
- req.type = 'request';
- cb.request_seq = req.seq = this.protocol.reqSeq++;
- this._reqCallbacks.push(cb);
-
- d.write(JSON.stringify(req));
- };
-
- client.emit('ready');
-
- client._onResponse({
- headers: { Type: 'connect' },
- body: {}
- });
- },
- debugBrk: true
- });
- this.child.kill = function() {
- self.error('isolate.kill is not implemented yet!');
- };
- } else {
- this.child = fork('--debug-brk', this.args);
- }
+ this.child = spawn(process.execPath, this.args);
+
+ this.child.stdout.on('data', this.childPrint.bind(this));
+ this.child.stderr.on('data', this.childPrint.bind(this));
}
this.pause();
+ var client = self.client = new Client(),
+ connectionAttempts = 0;
+
client.once('ready', function() {
- if (!client.isolates) self.stdout.write(' ok\n');
+ self.stdout.write(' ok\n');
// Restore breakpoints
breakpoints.forEach(function(bp) {
@@ -1689,14 +1656,11 @@ Interface.prototype.trySpawn = function(cb) {
function attemptConnect() {
++connectionAttempts;
self.stdout.write('.');
-
client.connect(port, host);
}
- if (!client.isolates) {
- setTimeout(function() {
- self.print('connecting..', true);
- attemptConnect();
- }, 50);
- }
+ setTimeout(function() {
+ self.print('connecting..', true);
+ attemptConnect();
+ }, 50);
};
View
69 lib/child_process.js
@@ -209,11 +209,11 @@ exports.fork = function(modulePath /*, args, options*/) {
options.env.NODE_CHANNEL_FD = 42;
// stdin is the IPC channel.
- if (!options.thread) options.stdinStream = createPipe(true);
+ options.stdinStream = createPipe(true);
var child = spawn(process.execPath, args, options);
- if (!options.thread) setupChannel(child, options.stdinStream);
+ setupChannel(child, options.stdinStream);
return child;
};
@@ -370,7 +370,7 @@ var spawn = exports.spawn = function(file, args, options) {
envPairs.push(key + '=' + env[key]);
}
- var child = (options && options.thread) ? (new Isolate) : (new ChildProcess);
+ var child = new ChildProcess();
child.spawn({
file: file,
@@ -379,8 +379,7 @@ var spawn = exports.spawn = function(file, args, options) {
windowsVerbatimArguments: !!(options && options.windowsVerbatimArguments),
envPairs: envPairs,
customFds: options ? options.customFds : null,
- stdinStream: options ? options.stdinStream : null,
- options: options
+ stdinStream: options ? options.stdinStream : null
});
return child;
@@ -537,63 +536,3 @@ ChildProcess.prototype.kill = function(sig) {
// TODO: raise error if r == -1?
}
};
-
-
-// Lazy loaded.
-var isolates = null;
-
-
-function Isolate() {
- if (!process.features.isolates) {
- throw new Error('Compiled without isolates support.');
- }
-
- if (!isolates) {
- isolates = process.binding('isolates');
- }
-
- this._handle = null;
-}
-inherits(Isolate, EventEmitter); // maybe inherit from ChildProcess?
-
-
-Isolate.prototype.spawn = function(options) {
- var self = this;
-
- if (self._handle) throw new Error('Isolate already running.');
- self._handle = isolates.create(options.args, options.options);
- if (!self._handle) throw new Error('Cannot create isolate.');
-
- self._handle.onmessage = function(msg, recvHandle) {
- msg = JSON.parse('' + msg);
-
- // Update simultaneous accepts on Windows
- net._setSimultaneousAccepts(recvHandle);
-
- self.emit('message', msg, recvHandle);
- };
-
- self._handle.onexit = function() {
- self._handle = null;
- self.emit('exit');
- };
-};
-
-
-Isolate.prototype.kill = function(sig) {
- if (!this._handle) throw new Error('Isolate not running.');
- // ignore silently for now, need a way to signal the other thread
-};
-
-
-Isolate.prototype.send = function(msg, sendHandle) {
- if (typeof msg === 'undefined') throw new TypeError('Bad argument.');
- if (!this._handle) throw new Error('Isolate not running.');
- msg = JSON.stringify(msg);
- msg = new Buffer(msg);
-
- // Update simultaneous accepts on Windows
- net._setSimultaneousAccepts(sendHandle);
-
- return this._handle.send(msg, sendHandle);
-};
View
12 node.gyp
@@ -8,7 +8,6 @@
'node_use_dtrace': 'false',
'node_use_openssl%': 'true',
'node_use_system_openssl%': 'false',
- 'node_use_isolates%': 'true',
'library_files': [
'src/node.js',
'lib/_debugger.js',
@@ -73,9 +72,7 @@
'src/cares_wrap.cc',
'src/handle_wrap.cc',
'src/node.cc',
- 'src/node_vars.cc',
'src/node_buffer.cc',
- 'src/node_isolate.cc',
'src/node_constants.cc',
'src/node_extensions.cc',
'src/node_file.cc',
@@ -95,12 +92,9 @@
'src/v8_typed_array.cc',
'src/udp_wrap.cc',
# headers to make for a more pleasant IDE experience
- 'src/ngx-queue.h',
'src/handle_wrap.h',
'src/node.h',
- 'src/node_vars.h',
'src/node_buffer.h',
- 'src/node_isolate.h',
'src/node_constants.h',
'src/node_crypto.h',
'src/node_extensions.h',
@@ -133,12 +127,6 @@
],
'conditions': [
- [ 'node_use_isolates=="true"', {
- 'defines': [ 'HAVE_ISOLATES=1' ],
- }, {
- 'defines': [ 'HAVE_ISOLATES=0' ],
- }],
-
[ 'node_use_openssl=="true"', {
'defines': [ 'HAVE_OPENSSL=1' ],
'sources': [ 'src/node_crypto.cc' ],
View
19 src/cares_wrap.cc
@@ -22,7 +22,6 @@
#include <assert.h>
#include <node.h>
#include <req_wrap.h>
-#include <node_vars.h>
#include <uv.h>
#include <string.h>
@@ -49,11 +48,6 @@
#endif
-#include <node_vars.h>
-#define oncomplete_sym NODE_VAR(oncomplete_sym)
-#define ares_channel NODE_VAR(ares_channel)
-
-
namespace node {
namespace cares_wrap {
@@ -75,6 +69,11 @@ using v8::Value;
typedef class ReqWrap<uv_getaddrinfo_t> GetAddrInfoReqWrap;
+static Persistent<String> oncomplete_sym;
+
+static ares_channel ares_channel;
+
+
static Local<Array> HostentToAddresses(struct hostent* host) {
HandleScope scope;
Local<Array> addresses = Array::New();
@@ -608,7 +607,7 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
if (status) {
// Error
- SetErrno(uv_last_error(Loop()));
+ SetErrno(uv_last_error(uv_default_loop()));
argv[0] = Local<Value>::New(Null());
} else {
// Success
@@ -711,7 +710,7 @@ static Handle<Value> GetAddrInfo(const Arguments& args) {
hints.ai_family = fam;
hints.ai_socktype = SOCK_STREAM;
- int r = uv_getaddrinfo(Loop(),
+ int r = uv_getaddrinfo(uv_default_loop(),
&req_wrap->req_,
AfterGetAddrInfo,
*hostname,
@@ -720,7 +719,7 @@ static Handle<Value> GetAddrInfo(const Arguments& args) {
req_wrap->Dispatched();
if (r) {
- SetErrno(uv_last_error(Loop()));
+ SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
return scope.Close(v8::Null());
} else {
@@ -737,7 +736,7 @@ static void Initialize(Handle<Object> target) {
assert(r == ARES_SUCCESS);
struct ares_options options;
- uv_ares_init_options(Loop(), &ares_channel, &options, 0);
+ uv_ares_init_options(uv_default_loop(), &ares_channel, &options, 0);
assert(r == 0);
NODE_SET_METHOD(target, "queryA", Query<QueryAWrap>);
View
9 src/fs_event_wrap.cc
@@ -21,7 +21,6 @@
#include <node.h>
#include <handle_wrap.h>
-#include <node_vars.h>
#include <stdlib.h>
@@ -110,15 +109,15 @@ Handle<Value> FSEventWrap::Start(const Arguments& args) {
String::Utf8Value path(args[0]->ToString());
- int r = uv_fs_event_init(Loop(), &wrap->handle_, *path, OnEvent, 0);
+ int r = uv_fs_event_init(uv_default_loop(), &wrap->handle_, *path, OnEvent, 0);
if (r == 0) {
// Check for persistent argument
if (!args[1]->IsTrue()) {
- uv_unref(Loop());
+ uv_unref(uv_default_loop());
}
wrap->initialized_ = true;
} else {
- SetErrno(uv_last_error(Loop()));
+ SetErrno(uv_last_error(uv_default_loop()));
}
return scope.Close(Integer::New(r));
@@ -146,7 +145,7 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
// assumption that a rename implicitly means an attribute change. Not too
// unreasonable, right? Still, we should revisit this before v1.0.
if (status) {
- SetErrno(uv_last_error(Loop()));
+ SetErrno(uv_last_error(uv_default_loop()));
eventStr = String::Empty();
}
else if (events & UV_RENAME) {
View
5 src/handle_wrap.cc
@@ -21,7 +21,6 @@
#include <node.h>
#include <handle_wrap.h>
-#include <node_vars.h>
namespace node {
@@ -71,7 +70,7 @@ Handle<Value> HandleWrap::Unref(const Arguments& args) {
}
wrap->unref = true;
- uv_unref(Loop());
+ uv_unref(uv_default_loop());
return v8::Undefined();
}
@@ -89,7 +88,7 @@ Handle<Value> HandleWrap::Ref(const Arguments& args) {
}
wrap->unref = false;
- uv_ref(Loop());
+ uv_ref(uv_default_loop());
return v8::Undefined();
}
View
109 src/ngx-queue.h
@@ -1,109 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_QUEUE_H_INCLUDED_
-#define _NGX_QUEUE_H_INCLUDED_
-
-#ifdef _WIN32
-# include <stddef.h>
-#endif
-
-typedef struct ngx_queue_s ngx_queue_t;
-
-struct ngx_queue_s {
- ngx_queue_t *prev;
- ngx_queue_t *next;
-};
-
-
-#define ngx_queue_init(q) \
- (q)->prev = q; \
- (q)->next = q
-
-
-#define ngx_queue_empty(h) \
- (h == (h)->prev)
-
-
-#define ngx_queue_insert_head(h, x) \
- (x)->next = (h)->next; \
- (x)->next->prev = x; \
- (x)->prev = h; \
- (h)->next = x
-
-
-#define ngx_queue_insert_after ngx_queue_insert_head
-
-
-#define ngx_queue_insert_tail(h, x) \
- (x)->prev = (h)->prev; \
- (x)->prev->next = x; \
- (x)->next = h; \
- (h)->prev = x
-
-
-#define ngx_queue_head(h) \
- (h)->next
-
-
-#define ngx_queue_last(h) \
- (h)->prev
-
-
-#define ngx_queue_sentinel(h) \
- (h)
-
-
-#define ngx_queue_next(q) \
- (q)->next
-
-
-#define ngx_queue_prev(q) \
- (q)->prev
-
-
-#if (NGX_DEBUG)
-
-#define ngx_queue_remove(x) \
- (x)->next->prev = (x)->prev; \
- (x)->prev->next = (x)->next; \
- (x)->prev = NULL; \
- (x)->next = NULL
-
-#else
-
-#define ngx_queue_remove(x) \
- (x)->next->prev = (x)->prev; \
- (x)->prev->next = (x)->next
-
-#endif
-
-
-#define ngx_queue_split(h, q, n) \
- (n)->prev = (h)->prev; \
- (n)->prev->next = n; \
- (n)->next = q; \
- (h)->prev = (q)->prev; \
- (h)->prev->next = h; \
- (q)->prev = n;
-
-
-#define ngx_queue_add(h, n) \
- (h)->prev->next = (n)->next; \
- (n)->next->prev = (h)->prev; \
- (h)->prev = (n)->prev; \
- (h)->prev->next = h;
-
-
-#define ngx_queue_data(q, type, link) \
- (type *) ((unsigned char *) q - offsetof(type, link))
-
-
-#define ngx_queue_foreach(q, h) \
- for ((q) = ngx_queue_head(h); (q) != (h); (q) = ngx_queue_next(q))
-
-
-#endif /* _NGX_QUEUE_H_INCLUDED_ */
View
280 src/node.cc
@@ -20,8 +20,6 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <node.h>
-#include <node_isolate.h>
-#include <node_internals.h>
#include <uv.h>
@@ -92,65 +90,81 @@ using namespace v8;
extern char **environ;
# endif
+namespace node {
-#include <node_vars.h>
-
-// We do the following to minimize the detal between v0.6 branch. We want to
-// use the variables as they were being used before.
-#define check_tick_watcher NODE_VAR(check_tick_watcher)
-#define code_symbol NODE_VAR(code_symbol)
-#define emit_symbol NODE_VAR(emit_symbol)
-#define errno_symbol NODE_VAR(errno_symbol)
-#define errpath_symbol NODE_VAR(errpath_symbol)
-#define gc_check NODE_VAR(gc_check)
-#define gc_idle NODE_VAR(gc_idle)
-#define gc_timer NODE_VAR(gc_timer)
-#define getbuf NODE_VAR(getbuf)
-#define heap_total_symbol NODE_VAR(heap_total_symbol)
-#define heap_used_symbol NODE_VAR(heap_used_symbol)
-#define listeners_symbol NODE_VAR(listeners_symbol)
-#define need_tick_cb NODE_VAR(need_tick_cb)
-#define prepare_tick_watcher NODE_VAR(prepare_tick_watcher)
-#define process NODE_VAR(process)
-#define rss_symbol NODE_VAR(rss_symbol)
-#define syscall_symbol NODE_VAR(syscall_symbol)
-#define tick_callback_sym NODE_VAR(tick_callback_sym)
-#define tick_spinner NODE_VAR(tick_spinner)
-#define tick_time_head NODE_VAR(tick_time_head)
-#define tick_times NODE_VAR(tick_times)
-#define uncaught_exception_symbol NODE_VAR(uncaught_exception_symbol)
-#define use_npn NODE_VAR(use_npn)
-#define use_sni NODE_VAR(use_sni)
-#define uncaught_exception_counter NODE_VAR(uncaught_exception_counter)
-#define binding_cache NODE_VAR(binding_cache)
-#define module_load_list NODE_VAR(module_load_list)
-#define node_isolate NODE_VAR(node_isolate)
-#define debugger_running NODE_VAR(debugger_running)
-#define prog_start_time NODE_VAR(prog_start_time)
-namespace node {
+static Persistent<Object> process;
-#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
+static Persistent<String> errno_symbol;
+static Persistent<String> syscall_symbol;
+static Persistent<String> errpath_symbol;
+static Persistent<String> code_symbol;
-static int option_end_index;
-static unsigned long max_stack_size;
-static unsigned short debug_port = 5858;
-static bool debug_wait_connect;
-static bool use_debug_agent;
-static const char* eval_string;
-static bool print_eval;
+static Persistent<String> rss_symbol;
+static Persistent<String> heap_total_symbol;
+static Persistent<String> heap_used_symbol;
-static void CheckStatus(uv_timer_t* watcher, int status);
+static Persistent<String> listeners_symbol;
+static Persistent<String> uncaught_exception_symbol;
+static Persistent<String> emit_symbol;
+
+
+static bool print_eval = false;
+static char *eval_string = NULL;
+static int option_end_index = 0;
+static bool use_debug_agent = false;
+static bool debug_wait_connect = false;
+static int debug_port=5858;
+static int max_stack_size = 0;
+static uv_check_t check_tick_watcher;
+static uv_prepare_t prepare_tick_watcher;
+static uv_idle_t tick_spinner;
+static bool need_tick_cb;
+static Persistent<String> tick_callback_sym;
-uv_loop_t* Loop() {
-#if defined(HAVE_ISOLATES) && HAVE_ISOLATES
- return Isolate::GetCurrent()->GetLoop();
+
+#ifdef OPENSSL_NPN_NEGOTIATED
+static bool use_npn = true;
#else
- return uv_default_loop();
+static bool use_npn = false;
#endif
-}
+#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
+static bool use_sni = true;
+#else
+static bool use_sni = false;
+#endif
+
+#ifdef __POSIX__
+// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
+// scoped at file-level rather than method-level to avoid excess stack usage.
+static char getbuf[PATH_MAX + 1];
+#endif
+
+// We need to notify V8 when we're idle so that it can run the garbage
+// collector. The interface to this is V8::IdleNotification(). It returns
+// true if the heap hasn't be fully compacted, and needs to be run again.
+// Returning false means that it doesn't have anymore work to do.
+//
+// A rather convoluted algorithm has been devised to determine when Node is
+// idle. You'll have to figure it out for yourself.
+static uv_check_t gc_check;
+static uv_idle_t gc_idle;
+static uv_timer_t gc_timer;
+bool need_gc;
+
+// process-relative uptime base, initialized at start-up
+static double prog_start_time;
+
+#define FAST_TICK 700.
+#define GC_WAIT_TIME 5000.
+#define RPM_SAMPLES 100
+#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
+static int64_t tick_times[RPM_SAMPLES];
+static int tick_time_head;
+
+static void CheckStatus(uv_timer_t* watcher, int status);
static void StartGCTimer () {
if (!uv_is_active((uv_handle_t*) &gc_timer)) {
@@ -178,7 +192,7 @@ static void Idle(uv_idle_t* watcher, int status) {
static void Check(uv_check_t* watcher, int status) {
assert(watcher == &gc_check);
- tick_times[tick_time_head] = uv_now(Loop());
+ tick_times[tick_time_head] = uv_now(uv_default_loop());
tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
StartGCTimer();
@@ -208,7 +222,7 @@ static void Tick(void) {
need_tick_cb = false;
if (uv_is_active((uv_handle_t*) &tick_spinner)) {
uv_idle_stop(&tick_spinner);
- uv_unref(Loop());
+ uv_unref(uv_default_loop());
}
HandleScope scope;
@@ -250,7 +264,7 @@ static Handle<Value> NeedTickCallback(const Arguments& args) {
// tick_spinner to keep the event loop alive long enough to handle it.
if (!uv_is_active((uv_handle_t*) &tick_spinner)) {
uv_idle_start(&tick_spinner, Spin);
- uv_ref(Loop());
+ uv_ref(uv_default_loop());
}
return Undefined();
}
@@ -1506,7 +1520,7 @@ static void CheckStatus(uv_timer_t* watcher, int status) {
}
}
- double d = uv_now(Loop()) - TICK_TIME(3);
+ double d = uv_now(uv_default_loop()) - TICK_TIME(3);
//printfb("timer d = %f\n", d);
@@ -1535,7 +1549,7 @@ static Handle<Value> Uptime(const Arguments& args) {
v8::Handle<v8::Value> UVCounters(const v8::Arguments& args) {
HandleScope scope;
- uv_counters_t* c = &Loop()->counters;
+ uv_counters_t* c = &uv_default_loop()->counters;
Local<Object> obj = Object::New();
@@ -1730,6 +1744,7 @@ static void OnFatalError(const char* location, const char* message) {
exit(1);
}
+static int uncaught_exception_counter = 0;
void FatalException(TryCatch &try_catch) {
HandleScope scope;
@@ -1789,6 +1804,9 @@ static void DebugBreakMessageHandler(const v8::Debug::Message& message) {
}
+Persistent<Object> binding_cache;
+Persistent<Array> module_load_list;
+
static Handle<Value> Binding(const Arguments& args) {
HandleScope scope;
@@ -1974,15 +1992,6 @@ static Handle<Object> GetFeatures() {
obj->Set(String::NewSymbol("tls"),
Boolean::New(get_builtin_module("crypto") != NULL));
-
- obj->Set(String::NewSymbol("isolates"),
-#if HAVE_ISOLATES
- True()
-#else
- False()
-#endif
- );
-
return scope.Close(obj);
}
@@ -1999,6 +2008,7 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
+
process->SetAccessor(String::New("title"),
ProcessTitleGetter,
ProcessTitleSetter);
@@ -2292,6 +2302,9 @@ static void ParseArgs(int argc, char **argv) {
}
+static Isolate* node_isolate = NULL;
+static volatile bool debugger_running = false;
+
static void EnableDebug(bool wait_connect) {
// If we're called from another thread, make sure to enter the right
// v8 isolate.
@@ -2322,7 +2335,6 @@ static void EnableDebug(bool wait_connect) {
#ifdef __POSIX__
-// FIXME this is positively unsafe with isolates/threads
static void EnableDebugSignalHandler(int signal) {
// Break once process will return execution to v8
v8::Debug::DebugBreak(node_isolate);
@@ -2525,7 +2537,10 @@ static Handle<Value> DebugPause(const Arguments& args) {
}
-char** ProcessInit(int argc, char *argv[]) {
+char** Init(int argc, char *argv[]) {
+ // Initialize prog_start_time to get relative uptime.
+ uv_uptime(&prog_start_time);
+
// Hack aroung with the argv pointer. Used for process.title = "blah".
argv = uv_setup_args(argc, argv);
@@ -2565,100 +2580,79 @@ char** ProcessInit(int argc, char *argv[]) {
#ifdef __POSIX__
// Ignore SIGPIPE
RegisterSignalHandler(SIGPIPE, SIG_IGN);
- // TODO decide whether to handle these signals per-process or per-thread
RegisterSignalHandler(SIGINT, SignalExit);
RegisterSignalHandler(SIGTERM, SignalExit);
#endif // __POSIX__
- return argv;
-}
-
-
-void EmitExit(v8::Handle<v8::Object> process_l) {
- // process.emit('exit')
- Local<Value> emit_v = process_l->Get(String::New("emit"));
- assert(emit_v->IsFunction());
- Local<Function> emit = Local<Function>::Cast(emit_v);
- Local<Value> args[] = { String::New("exit") };
- TryCatch try_catch;
- emit->Call(process_l, 1, args);
- if (try_catch.HasCaught()) {
- FatalException(try_catch);
- }
-}
-
-
-// Create a new isolate with node::Isolate::New() before you call this function
-void StartThread(node::Isolate* isolate,
- int argc,
- char** argv) {
- HandleScope scope;
-
- assert(node::Isolate::GetCurrent() == isolate);
-
- uv_loop_t* loop = isolate->GetLoop();
- uv_prepare_init(loop, &prepare_tick_watcher);
+ uv_prepare_init(uv_default_loop(), &prepare_tick_watcher);
uv_prepare_start(&prepare_tick_watcher, PrepareTick);
- uv_unref(loop);
+ uv_unref(uv_default_loop());
- uv_check_init(loop, &check_tick_watcher);
+ uv_check_init(uv_default_loop(), &check_tick_watcher);
uv_check_start(&check_tick_watcher, node::CheckTick);
- uv_unref(loop);
+ uv_unref(uv_default_loop());
- uv_idle_init(loop, &tick_spinner);
- uv_unref(loop);
+ uv_idle_init(uv_default_loop(), &tick_spinner);
+ uv_unref(uv_default_loop());
- uv_check_init(loop, &gc_check);
+ uv_check_init(uv_default_loop(), &gc_check);
uv_check_start(&gc_check, node::Check);
- uv_unref(loop);
+ uv_unref(uv_default_loop());
- uv_idle_init(loop, &gc_idle);
- uv_unref(loop);
+ uv_idle_init(uv_default_loop(), &gc_idle);
+ uv_unref(uv_default_loop());
- uv_timer_init(loop, &gc_timer);
- uv_unref(loop);
+ uv_timer_init(uv_default_loop(), &gc_timer);
+ uv_unref(uv_default_loop());
V8::SetFatalErrorHandler(node::OnFatalError);
// Fetch a reference to the main isolate, so we have a reference to it
// even when we need it to access it from another (debugger) thread.
- node_isolate = v8::Isolate::GetCurrent();
+ node_isolate = Isolate::GetCurrent();
- // Only main isolate is allowed to run a debug agent and listen for signals
- if (isolate->id_ == 1) {
- // If the --debug flag was specified then initialize the debug thread.
- if (use_debug_agent) {
- EnableDebug(debug_wait_connect);
- } else {
+ // If the --debug flag was specified then initialize the debug thread.
+ if (use_debug_agent) {
+ EnableDebug(debug_wait_connect);
+ } else {
#ifdef _WIN32
- RegisterDebugSignalHandler();
+ RegisterDebugSignalHandler();
#else // Posix
- RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
+ RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
#endif // __POSIX__
- }
- } else if (isolate->debug_state != Isolate::kNone) {
- isolate->debugger_instance->Init();
}
- Handle<Object> process_l = SetupProcessObject(argc, argv);
-
- process_l->Set(String::NewSymbol("tid"),
- Integer::NewFromUnsigned(isolate->id_));
+ return argv;
+}
- // TODO check (isolate->channel_ != NULL)
- if (isolate->id_ > 1) {
- process_l->Set(String::NewSymbol("_send"),
- FunctionTemplate::New(Isolate::Send)->GetFunction());
- process_l->Set(String::NewSymbol("_exit"),
- FunctionTemplate::New(Isolate::Unref)->GetFunction());
+void EmitExit(v8::Handle<v8::Object> process_l) {
+ // process.emit('exit')
+ Local<Value> emit_v = process_l->Get(String::New("emit"));
+ assert(emit_v->IsFunction());
+ Local<Function> emit = Local<Function>::Cast(emit_v);
+ Local<Value> args[] = { String::New("exit") };
+ TryCatch try_catch;
+ emit->Call(process_l, 1, args);
+ if (try_catch.HasCaught()) {
+ FatalException(try_catch);
}
+}
- // FIXME crashes with "CHECK(heap->isolate() == Isolate::Current()) failed"
- //v8_typed_array::AttachBindings(v8::Context::GetCurrent()->Global());
- // Initialize prog_start_time to get relative uptime.
- uv_uptime(&prog_start_time);
+int Start(int argc, char *argv[]) {
+ // This needs to run *before* V8::Initialize()
+ argv = Init(argc, argv);
+
+ v8::V8::Initialize();
+ v8::HandleScope handle_scope;
+
+ // Create the one and only Context.
+ Persistent<v8::Context> context = v8::Context::New();
+ v8::Context::Scope context_scope(context);
+
+ Handle<Object> process_l = SetupProcessObject(argc, argv);
+ v8_typed_array::AttachBindings(context->Global());
// Create all the objects, load modules, do everything.
// so your next reading stop should be node::Load()!
@@ -2669,29 +2663,13 @@ void StartThread(node::Isolate* isolate,
// there are no watchers on the loop (except for the ones that were
// uv_unref'd) then this function exits. As long as there are active
// watchers, it blocks.
- uv_run(loop);
+ uv_run(uv_default_loop());
EmitExit(process_l);
-}
-
-
-int Start(int argc, char *argv[]) {
- // This needs to run *before* V8::Initialize()
- argv = ProcessInit(argc, argv);
-
- v8::V8::Initialize();
- v8::HandleScope handle_scope;
-
- // Create the main node::Isolate object
- node::Isolate::Initialize();
- Isolate* isolate = new node::Isolate();
- isolate->tid_ = (uv_thread_t) -1;
- isolate->Enter();
- StartThread(isolate, argc, argv);
- isolate->Dispose();
#ifndef NDEBUG
// Clean up.
+ context.Dispose();
V8::Dispose();
#endif // NDEBUG
View
4 src/node.h
@@ -84,10 +84,6 @@ v8::Handle<v8::Object> SetupProcessObject(int argc, char *argv[]);
void Load(v8::Handle<v8::Object> process);
void EmitExit(v8::Handle<v8::Object> process);
-// Returns the loop for the current isolate. If compiled with
-// --without-isolates then this will always return uv_default_loop();
-uv_loop_t* Loop();
-
#define NODE_PSYMBOL(s) \
v8::Persistent<v8::String>::New(v8::String::NewSymbol(s))
View
32 src/node.js
@@ -120,33 +120,6 @@
});
}
}
-
- if (process.tid === 1) return;
-
- var net = NativeModule.require('net');
-
- // isolate initialization
- process.send = function(msg, sendHandle) {
- if (typeof msg === 'undefined') throw new TypeError('Bad argument.');
- msg = JSON.stringify(msg);
- msg = new Buffer(msg);
-
- // Update simultaneous accepts on Windows
- net._setSimultaneousAccepts(sendHandle);
-
- return process._send(msg, sendHandle);
- };
-
- process._onmessage = function(msg, recvHandle) {
- msg = JSON.parse('' + msg);
-
- // Update simultaneous accepts on Windows
- net._setSimultaneousAccepts(recvHandle);
-
- process.emit('message', msg, recvHandle);
- };
-
- process.exit = process._exit;
}
startup.globalVariables = function() {
@@ -455,11 +428,6 @@
cp._forkChild();
assert(process.send);
- } else if (process.tid !== 1) {
- // Load tcp_wrap to avoid situation where we might immediately receive
- // a message.
- // FIXME is this really necessary?
- process.binding('tcp_wrap');
}
}
View
68 src/node_buffer.cc
@@ -36,12 +36,6 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#include <node_vars.h>
-#define length_symbol NODE_VAR(length_symbol)
-#define chars_written_sym NODE_VAR(chars_written_sym)
-#define write_sym NODE_VAR(write_sym)
-#define buffer_constructor_template NODE_VAR(buffer_constructor_template)
-
namespace node {
using namespace v8;
@@ -67,6 +61,10 @@ using namespace v8;
}
+static Persistent<String> length_symbol;
+static Persistent<String> chars_written_sym;
+static Persistent<String> write_sym;
+Persistent<FunctionTemplate> Buffer::constructor_template;
static inline size_t base64_decoded_size(const char *src, size_t size) {
@@ -132,7 +130,7 @@ Buffer* Buffer::New(size_t length) {
HandleScope scope;
Local<Value> arg = Integer::NewFromUnsigned(length);
- Local<Object> b = buffer_constructor_template->GetFunction()->NewInstance(1, &arg);
+ Local<Object> b = constructor_template->GetFunction()->NewInstance(1, &arg);
if (b.IsEmpty()) return NULL;
return ObjectWrap::Unwrap<Buffer>(b);
@@ -143,7 +141,7 @@ Buffer* Buffer::New(char* data, size_t length) {
HandleScope scope;
Local<Value> arg = Integer::NewFromUnsigned(0);
- Local<Object> obj = buffer_constructor_template->GetFunction()->NewInstance(1, &arg);
+ Local<Object> obj = constructor_template->GetFunction()->NewInstance(1, &arg);
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(obj);
buffer->Replace(data, length, NULL, NULL);
@@ -157,7 +155,7 @@ Buffer* Buffer::New(char *data, size_t length,
HandleScope scope;
Local<Value> arg = Integer::NewFromUnsigned(0);
- Local<Object> obj = buffer_constructor_template->GetFunction()->NewInstance(1, &arg);
+ Local<Object> obj = constructor_template->GetFunction()->NewInstance(1, &arg);
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(obj);
buffer->Replace(data, length, callback, hint);
@@ -168,7 +166,7 @@ Buffer* Buffer::New(char *data, size_t length,
Handle<Value> Buffer::New(const Arguments &args) {
if (!args.IsConstructCall()) {
- return FromConstructorTemplate(buffer_constructor_template, args);
+ return FromConstructorTemplate(constructor_template, args);
}
HandleScope scope;
@@ -470,7 +468,7 @@ Handle<Value> Buffer::Utf8Write(const Arguments &args) {
int length = s->Length();
if (length == 0) {
- buffer_constructor_template->GetFunction()->Set(chars_written_sym,
+ constructor_template->GetFunction()->Set(chars_written_sym,
Integer::New(0));
return scope.Close(Integer::New(0));
}
@@ -494,7 +492,7 @@ Handle<Value> Buffer::Utf8Write(const Arguments &args) {
(String::HINT_MANY_WRITES_EXPECTED |
String::NO_NULL_TERMINATION));
- buffer_constructor_template->GetFunction()->Set(chars_written_sym,
+ constructor_template->GetFunction()->Set(chars_written_sym,
Integer::New(char_written));
return scope.Close(Integer::New(written));
@@ -532,7 +530,7 @@ Handle<Value> Buffer::Ucs2Write(const Arguments &args) {
(String::HINT_MANY_WRITES_EXPECTED |
String::NO_NULL_TERMINATION));
- buffer_constructor_template->GetFunction()->Set(chars_written_sym,
+ constructor_template->GetFunction()->Set(chars_written_sym,
Integer::New(written));
return scope.Close(Integer::New(written * 2));
@@ -571,7 +569,7 @@ Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
(String::HINT_MANY_WRITES_EXPECTED |
String::NO_NULL_TERMINATION));
- buffer_constructor_template->GetFunction()->Set(chars_written_sym,
+ constructor_template->GetFunction()->Set(chars_written_sym,
Integer::New(written));
return scope.Close(Integer::New(written));
@@ -661,7 +659,7 @@ Handle<Value> Buffer::Base64Write(const Arguments &args) {
*dst++ = ((c & 0x03) << 6) | (d & 0x3F);
}
- buffer_constructor_template->GetFunction()->Set(chars_written_sym,
+ constructor_template->GetFunction()->Set(chars_written_sym,
Integer::New(s.length()));
return scope.Close(Integer::New(dst - start));
@@ -695,7 +693,7 @@ Handle<Value> Buffer::BinaryWrite(const Arguments &args) {
int written = DecodeWrite(p, max_length, s, BINARY);
- buffer_constructor_template->GetFunction()->Set(chars_written_sym,
+ constructor_template->GetFunction()->Set(chars_written_sym,
Integer::New(written));
return scope.Close(Integer::New(written));
@@ -747,7 +745,7 @@ bool Buffer::HasInstance(v8::Handle<v8::Value> val) {
return true;
// Also check for SlowBuffers that are empty.
- if (buffer_constructor_template->HasInstance(obj))
+ if (constructor_template->HasInstance(obj))
return true;
return false;
@@ -761,35 +759,35 @@ void Buffer::Initialize(Handle<Object> target) {
chars_written_sym = Persistent<String>::New(String::NewSymbol("_charsWritten"));
Local<FunctionTemplate> t = FunctionTemplate::New(Buffer::New);
- buffer_constructor_template = Persistent<FunctionTemplate>::New(t);
- buffer_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
- buffer_constructor_template->SetClassName(String::NewSymbol("SlowBuffer"));
+ constructor_template = Persistent<FunctionTemplate>::New(t);
+ constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
+ constructor_template->SetClassName(String::NewSymbol("SlowBuffer"));
// copy free
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "binarySlice", Buffer::BinarySlice);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "asciiSlice", Buffer::AsciiSlice);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "base64Slice", Buffer::Base64Slice);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "ucs2Slice", Buffer::Ucs2Slice);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "binarySlice", Buffer::BinarySlice);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiSlice", Buffer::AsciiSlice);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Slice", Buffer::Base64Slice);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "ucs2Slice", Buffer::Ucs2Slice);
// TODO NODE_SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice);
// copy
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "utf8Slice", Buffer::Utf8Slice);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Slice", Buffer::Utf8Slice);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "utf8Write", Buffer::Utf8Write);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "asciiWrite", Buffer::AsciiWrite);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "binaryWrite", Buffer::BinaryWrite);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "base64Write", Buffer::Base64Write);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "ucs2Write", Buffer::Ucs2Write);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "fill", Buffer::Fill);
- NODE_SET_PROTOTYPE_METHOD(buffer_constructor_template, "copy", Buffer::Copy);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Write", Buffer::Utf8Write);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiWrite", Buffer::AsciiWrite);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "binaryWrite", Buffer::BinaryWrite);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Write", Buffer::Base64Write);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "ucs2Write", Buffer::Ucs2Write);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "fill", Buffer::Fill);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template, "copy", Buffer::Copy);
- NODE_SET_METHOD(buffer_constructor_template->GetFunction(),
+ NODE_SET_METHOD(constructor_template->GetFunction(),
"byteLength",
Buffer::ByteLength);
- NODE_SET_METHOD(buffer_constructor_template->GetFunction(),
+ NODE_SET_METHOD(constructor_template->GetFunction(),
"makeFastBuffer",
Buffer::MakeFastBuffer);
- target->Set(String::NewSymbol("SlowBuffer"), buffer_constructor_template->GetFunction());
+ target->Set(String::NewSymbol("SlowBuffer"), constructor_template->GetFunction());
}
View
1  src/node_buffer.h
@@ -65,6 +65,7 @@ namespace node {
class NODE_EXTERN Buffer: public ObjectWrap {
public:
+ static v8::Persistent<v8::FunctionTemplate> constructor_template;
static bool HasInstance(v8::Handle<v8::Value> val);
View
47 src/node_crypto.cc
@@ -24,7 +24,6 @@
#include <node.h>
#include <node_buffer.h>
-#include <node_vars.h>
#include <node_root_certs.h>
#include <string.h>
@@ -64,34 +63,29 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
| XN_FLAG_SEP_MULTILINE
| XN_FLAG_FN_SN;
-
-#include <node_vars.h>
-// We do the following to minimize the detal between v0.6 branch. We want to
-// use the variables as they were being used before.
-#define on_headers_sym NODE_VAR(on_headers_sym)
-#define errno_symbol NODE_VAR(errno_symbol)
-#define syscall_symbol NODE_VAR(syscall_symbol)
-#define subject_symbol NODE_VAR(subject_symbol)
-#define subjectaltname_symbol NODE_VAR(subjectaltname_symbol)
-#define modulus_symbol NODE_VAR(modulus_symbol)
-#define exponent_symbol NODE_VAR(exponent_symbol)
-#define issuer_symbol NODE_VAR(issuer_symbol)
-#define valid_from_symbol NODE_VAR(valid_from_symbol)
-#define valid_to_symbol NODE_VAR(valid_to_symbol)
-#define fingerprint_symbol NODE_VAR(fingerprint_symbol)
-#define name_symbol NODE_VAR(name_symbol)
-#define version_symbol NODE_VAR(version_symbol)
-#define ext_key_usage_symbol NODE_VAR(ext_key_usage_symbol)
-#define secure_context_constructor NODE_VAR(secure_context_constructor)
-
-
namespace node {
namespace crypto {
-static uv_rwlock_t* locks;
-
using namespace v8;
+static Persistent<String> errno_symbol;
+static Persistent<String> syscall_symbol;
+static Persistent<String> subject_symbol;
+static Persistent<String> subjectaltname_symbol;
+static Persistent<String> modulus_symbol;
+static Persistent<String> exponent_symbol;
+static Persistent<String> issuer_symbol;
+static Persistent<String> valid_from_symbol;
+static Persistent<String> valid_to_symbol;
+static Persistent<String> fingerprint_symbol;
+static Persistent<String> name_symbol;
+static Persistent<String> version_symbol;
+static Persistent<String> ext_key_usage_symbol;
+
+static Persistent<FunctionTemplate> secure_context_constructor;
+
+static uv_rwlock_t* locks;
+
static unsigned long crypto_id_cb(void) {
#ifdef _WIN32
@@ -4165,8 +4159,7 @@ PBKDF2(const Arguments& args) {
req = new uv_work_t();
req->data = request;
- uv_queue_work(Loop(), req, EIO_PBKDF2, EIO_PBKDF2After);
-
+ uv_queue_work(uv_default_loop(), req, EIO_PBKDF2, EIO_PBKDF2After);
return Undefined();
err:
@@ -4288,7 +4281,7 @@ Handle<Value> RandomBytes(const Arguments& args) {
Local<Function> callback_v = Local<Function>(Function::Cast(*args[1]));
req->callback_ = Persistent<Function>::New(callback_v);
- uv_queue_work(Loop(),
+ uv_queue_work(uv_default_loop(),
&req->work_req_,
RandomBytesWork<generator>,
RandomBytesAfter<generator>);
View
4 src/node_extensions.h
@@ -35,10 +35,6 @@ NODE_EXT_LIST_ITEM(node_signal_watcher)
NODE_EXT_LIST_ITEM(node_os)
NODE_EXT_LIST_ITEM(node_zlib)
-#if defined(HAVE_ISOLATES) && HAVE_ISOLATES
-NODE_EXT_LIST_ITEM(node_isolates)
-#endif
-
// libuv rewrite
NODE_EXT_LIST_ITEM(node_timer_wrap)
NODE_EXT_LIST_ITEM(node_tcp_wrap)
View
54 src/node_file.cc
@@ -22,7 +22,6 @@
#include "node.h"
#include "node_file.h"
#include "node_buffer.h"
-#include <node_vars.h>
#ifdef __POSIX__
# include "node_stat_watcher.h"
#endif
@@ -41,30 +40,6 @@
#endif
-#include <node_vars.h>
-// We do the following to minimize the detal between v0.6 branch. We want to
-// use the variables as they were being used before.
-#define on_headers_sym NODE_VAR(on_headers_sym)
-#define encoding_symbol NODE_VAR(encoding_symbol)
-#define errno_symbol NODE_VAR(errno_symbol)
-#define buf_symbol NODE_VAR(buf_symbol)
-#define oncomplete_sym NODE_VAR(oncomplete_sym)
-#define stats_constructor_template NODE_VAR(stats_constructor_template)
-#define dev_symbol NODE_VAR(dev_symbol)
-#define ino_symbol NODE_VAR(ino_symbol)
-#define mode_symbol NODE_VAR(mode_symbol)
-#define nlink_symbol NODE_VAR(nlink_symbol)
-#define uid_symbol NODE_VAR(uid_symbol)
-#define gid_symbol NODE_VAR(gid_symbol)
-#define rdev_symbol NODE_VAR(rdev_symbol)
-#define size_symbol NODE_VAR(size_symbol)
-#define blksize_symbol NODE_VAR(blksize_symbol)
-#define blocks_symbol NODE_VAR(blocks_symbol)
-#define atime_symbol NODE_VAR(atime_symbol)
-#define mtime_symbol NODE_VAR(mtime_symbol)
-#define ctime_symbol NODE_VAR(ctime_symbol)
-
-
namespace node {
using namespace v8;
@@ -78,6 +53,11 @@ using namespace v8;
typedef class ReqWrap<uv_fs_t> FSReqWrap;
+static Persistent<String> encoding_symbol;
+static Persistent<String> errno_symbol;
+static Persistent<String> buf_symbol;
+static Persistent<String> oncomplete_sym;
+
#ifdef _LARGEFILE_SOURCE
static inline int IsInt64(double x) {
@@ -229,7 +209,7 @@ struct fs_req_wrap {
#define ASYNC_CALL(func, callback, ...) \
FSReqWrap* req_wrap = new FSReqWrap(); \
- int r = uv_fs_##func(Loop(), &req_wrap->req_, \
+ int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
__VA_ARGS__, After); \
req_wrap->object_->Set(oncomplete_sym, callback); \
req_wrap->Dispatched(); \
@@ -237,16 +217,16 @@ struct fs_req_wrap {
uv_fs_t* req = &req_wrap->req_; \
req->result = r; \
req->path = NULL; \
- req->errorno = uv_last_error(Loop()).code; \
+ req->errorno = uv_last_error(uv_default_loop()).code; \
After(req); \
} \
return scope.Close(req_wrap->object_);
#define SYNC_CALL(func, path, ...) \
fs_req_wrap req_wrap; \
- int result = uv_fs_##func(Loop(), &req_wrap.req, __VA_ARGS__, NULL); \
+ int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \
if (result < 0) { \
- int code = uv_last_error(Loop()).code; \
+ int code = uv_last_error(uv_default_loop()).code; \
return ThrowException(UVException(code, #func, "", path)); \
}
@@ -273,6 +253,22 @@ static Handle<Value> Close(const Arguments& args) {
}
+static Persistent<FunctionTemplate> stats_constructor_template;
+
+static Persistent<String> dev_symbol;
+static Persistent<String> ino_symbol;
+static Persistent<String> mode_symbol;
+static Persistent<String> nlink_symbol;
+static Persistent<String> uid_symbol;
+static Persistent<String> gid_symbol;
+static Persistent<String> rdev_symbol;
+static Persistent<String> size_symbol;
+static Persistent<String> blksize_symbol;
+static Persistent<String> blocks_symbol;
+static Persistent<String> atime_symbol;
+static Persistent<String> mtime_symbol;
+static Persistent<String> ctime_symbol;
+
Local<Object> BuildStatsObject(NODE_STAT_STRUCT *s) {
HandleScope scope;
View
98 src/node_http_parser.cc
@@ -47,57 +47,61 @@
// allocations.
-#include <node_vars.h>
-// We do the following to minimize the detal between v0.6 branch. We want to
-// use the variables as they were being used before.
-#define on_headers_sym NODE_VAR(on_headers_sym)
-#define on_headers_complete_sym NODE_VAR(on_headers_complete_sym)
-#define on_body_sym NODE_VAR(on_body_sym)
-#define on_message_complete_sym NODE_VAR(on_message_complete_sym)
-#define delete_sym NODE_VAR(delete_sym)
-#define get_sym NODE_VAR(get_sym)
-#define head_sym NODE_VAR(head_sym)
-#define post_sym NODE_VAR(post_sym)
-#define put_sym NODE_VAR(put_sym)
-#define connect_sym NODE_VAR(connect_sym)
-#define options_sym NODE_VAR(options_sym)
-#define trace_sym NODE_VAR(trace_sym)
-#define patch_sym NODE_VAR(patch_sym)
-#define copy_sym NODE_VAR(copy_sym)
-#define lock_sym NODE_VAR(lock_sym)
-#define mkcol_sym NODE_VAR(mkcol_sym)
-#define move_sym NODE_VAR(move_sym)
-#define propfind_sym NODE_VAR(propfind_sym)
-#define proppatch_sym NODE_VAR(proppatch_sym)
-#define unlock_sym NODE_VAR(unlock_sym)
-#define report_sym NODE_VAR(report_sym)
-#define mkactivity_sym NODE_VAR(mkactivity_sym)
-#define checkout_sym NODE_VAR(checkout_sym)
-#define merge_sym NODE_VAR(merge_sym)
-#define msearch_sym NODE_VAR(msearch_sym)
-#define notify_sym NODE_VAR(notify_sym)
-#define subscribe_sym NODE_VAR(subscribe_sym)
-#define unsubscribe_sym NODE_VAR(unsubscribe_sym)
-#define unknown_method_sym NODE_VAR(unknown_method_sym)
-#define method_sym NODE_VAR(method_sym)
-#define status_code_sym NODE_VAR(status_code_sym)
-#define http_version_sym NODE_VAR(http_version_sym)
-#define version_major_sym NODE_VAR(version_major_sym)
-#define version_minor_sym NODE_VAR(version_minor_sym)
-#define should_keep_alive_sym NODE_VAR(should_keep_alive_sym)
-#define upgrade_sym NODE_VAR(upgrade_sym)
-#define headers_sym NODE_VAR(headers_sym)
-#define url_sym NODE_VAR(url_sym)
-#define settings NODE_VAR(settings)
-#define current_buffer NODE_VAR(current_buffer)
-#define current_buffer_data NODE_VAR(current_buffer_data)
-#define current_buffer_len NODE_VAR(current_buffer_len)
-
-
namespace node {
using namespace v8;
+static Persistent<String> on_headers_sym;
+static Persistent<String> on_headers_complete_sym;
+static Persistent<String> on_body_sym;
+static Persistent<String> on_message_complete_sym;
+
+static Persistent<String> delete_sym;
+static Persistent<String> get_sym;
+static Persistent<String> head_sym;
+static Persistent<String> post_sym;
+static Persistent<String> put_sym;
+static Persistent<String> connect_sym;
+static Persistent<String> options_sym;
+static Persistent<String> trace_sym;
+static Persistent<String> patch_sym;
+static Persistent<String> copy_sym;
+static Persistent<String> lock_sym;
+static Persistent<String> mkcol_sym;
+static Persistent<String> move_sym;
+static Persistent<String> propfind_sym;
+static Persistent<String> proppatch_sym;
+static Persistent<String> unlock_sym;
+static Persistent<String> report_sym;
+static Persistent<String> mkactivity_sym;
+static Persistent<String> checkout_sym;
+static Persistent<String> merge_sym;
+static Persistent<String> msearch_sym;
+static Persistent<String> notify_sym;
+static Persistent<String> subscribe_sym;
+static Persistent<String> unsubscribe_sym;
+static Persistent<String> unknown_method_sym;
+
+static Persistent<String> method_sym;
+static Persistent<String> status_code_sym;
+static Persistent<String> http_version_sym;
+static Persistent<String> version_major_sym;
+static Persistent<String> version_minor_sym;
+static Persistent<String> should_keep_alive_sym;
+static Persistent<String> upgrade_sym;
+static Persistent<String> headers_sym;
+static Persistent<String> url_sym;
+
+static struct http_parser_settings settings;
+
+
+// This is a hack to get the current_buffer to the callbacks with the least
+// amount of overhead. Nothing else will run while http_parser_execute()
+// runs, therefore this pointer can be set and used for the execution.
+static Local<Value>* current_buffer;
+static char* current_buffer_data;
+static size_t current_buffer_len;
+
#define HTTP_CB(name) \
static int name(http_parser* p_) { \
View
15 src/node_internals.h
@@ -24,13 +24,6 @@
namespace node {
-// This function starts an Isolate. This function is defined in node.cc
-// currently so that we minimize the diff between master and v0.6 for easy
-// merging. In the future, when v0.6 is extinct, StartThread should be moved
-// to node_isolate.cc.
-class Isolate;
-void StartThread(Isolate* isolate, int argc, char** argv);
-
#ifndef offset_of
// g++ in strict mode complains loudly about the system offsetof() macro
// because it uses NULL as the base address.
@@ -47,14 +40,6 @@ void StartThread(Isolate* isolate, int argc, char** argv);
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
#endif
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
- TypeName(); \
- DISALLOW_COPY_AND_ASSIGN(TypeName)
-
} // namespace node
#endif // SRC_NODE_INTERNALS_H_
View
815 src/node_isolate.cc
@@ -1,815 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-#include <v8.h>
-#include <v8-debug.h>
-#include <node.h>
-#include <node_buffer.h>
-#include <node_isolate.h>
-#include <node_internals.h>
-#include <node_object_wrap.h>
-#include <tcp_wrap.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-
-#define isolate_debugger_constructor NODE_VAR(isolate_debugger_constructor)
-
-#define ISOLATEMESSAGE_SHARED_STREAM 0x0001
-
-
-namespace node {
-
-using v8::Arguments;
-using v8::Array;
-using v8::Context;
-using v8::False;
-using v8::Function;
-using v8::FunctionTemplate;
-using v8::Handle;
-using v8::HandleScope;
-using v8::Integer;
-using v8::Local;
-using v8::Null;
-using v8::Object;
-using v8::ObjectTemplate;
-using v8::Persistent;
-using v8::String;
-using v8::True;
-using v8::Undefined;
-using v8::Value;
-using v8::Undefined;
-
-static volatile bool initialized;
-static volatile int id;
-static volatile int isolate_count;
-static ngx_queue_t isolate_list;
-static uv_mutex_t isolate_mutex;
-
-#ifdef NDEBUG
-# define IF_DEBUG(expr)
-#else
-# define IF_DEBUG(expr) expr;
-#endif
-
-template <class T>
-class Queue {
-public:
- Queue() {
- if (uv_mutex_init(&mutex_)) abort();
- ngx_queue_init(&queue_);
- }
-
- ~Queue() {
- IF_DEBUG({
- uv_mutex_lock(&mutex_);
- assert(ngx_queue_empty(&queue_));
- uv_mutex_unlock(&mutex_);
- })
- uv_mutex_destroy(&mutex_);
- }
-
- void Produce(T item) {
- Message* m = new Message;
- m->item_ = item;
-
- uv_mutex_lock(&mutex_);
- ngx_queue_insert_tail(&queue_, &m->queue_);
- uv_mutex_unlock(&mutex_);
- }
-
- bool Consume(T& item) {
- ngx_queue_t* q = NULL;
-
- uv_mutex_lock(&mutex_);
- if (!ngx_queue_empty(&queue_)) {
- q = ngx_queue_head(&queue_);
- ngx_queue_remove(q);
- }
- uv_mutex_unlock(&mutex_);
-
- if (q == NULL) return false;
-
- Message* m = ngx_queue_data(q, Message, queue_);
- item = m->item_;
- delete m;
-
- return true;
- }
-
-private:
- struct Message {
- ngx_queue_t queue_;
- T item_;
- };
-
- ngx_queue_t queue_;
- uv_mutex_t mutex_;
-};
-
-
-template <class T>
-class Channel {
-public:
- typedef void (*Callback)(T item, void* arg);
-
- Channel(uv_loop_t* loop, Callback callback, void* arg) {
- callback_ = callback;
- arg_ = arg;
- uv_async_init(loop, &async_, OnMessage);
- uv_unref(loop);
- }
-
- ~Channel() {
- uv_ref(async_.loop);
- uv_close(reinterpret_cast<uv_handle_t*>(&async_), NULL);
- }
-
- void Send(T item) {
- queue_.Produce(item);
- uv_async_send(&async_);
- }
-
-private:
- static void OnMessage(uv_async_t* handle, int status) {
- Channel* c = container_of(handle, Channel, async_);
- c->OnMessage();
- }
-
- void OnMessage() {
- T item;
- while (queue_.Consume(item)) callback_(item, arg_);
- }
-
- void* arg_;
- Callback callback_;
- uv_async_t async_;
- Queue<T> queue_;
-};
-
-
-struct IsolateMessage {
- int flags;
- struct {
- size_t size_;
- char* buffer_;
- } data_;
- uv_stream_info_t shared_stream_info_;
-
- IsolateMessage(const char* buffer, size_t size,
- uv_stream_info_t* shared_stream_info) {
- flags = 0;
-
- // make a copy for now
- data_.size_ = size;
- data_.buffer_ = new char[size];
- memcpy(data_.buffer_, buffer, size);
-
- if (shared_stream_info) {
- flags |= ISOLATEMESSAGE_SHARED_STREAM;
- shared_stream_info_ = *shared_stream_info;
- }
- }
-
- ~IsolateMessage() {
- delete[] data_.buffer_;
- }
-
- static void Free(char* data, void* arg) {
- IsolateMessage* msg = static_cast<IsolateMessage*>(arg);
- assert(data == msg->data_.buffer_);
- delete msg;
- }
-};
-
-
-class IsolateChannel: public Channel<IsolateMessage*> {
-public:
- IsolateChannel(uv_loop_t* loop, Callback callback, void* arg)
- : Channel<IsolateMessage*>(loop, callback, arg)
- {
- }
-};
-
-
-Handle<Value> Isolate::Send(const Arguments& args) {
- HandleScope scope;
-
- Isolate* isolate = Isolate::GetCurrent();
- assert(Buffer::HasInstance(args[0]));
- assert(isolate->send_channel_ != NULL);
-
- Local<Object> obj = args[0]->ToObject();
- const char* data = Buffer::Data(obj);
- size_t size = Buffer::Length(obj);
-
- IsolateMessage* msg;
-
- if (args[1]->IsObject()) {
- uv_stream_info_t stream_info;
-
- Local<Object> send_stream_obj = args[1]->ToObject();
- assert(send_stream_obj->InternalFieldCount() > 0);
- StreamWrap* send_stream_wrap = static_cast<StreamWrap*>(
- send_stream_obj->GetPointerFromInternalField(0));
- uv_stream_t* send_stream = send_stream_wrap->GetStream();
- int r = uv_export(send_stream, &stream_info);
- assert(r == 0);
- msg = new IsolateMessage(data, size, &stream_info);
- } else {
- msg = new IsolateMessage(data, size, NULL);
- }
-
- isolate->send_channel_->Send(msg);
-
- return Undefined();
-}
-
-
-Handle<Value> Isolate::Unref(const Arguments& args) {
- HandleScope scope;
-
- Isolate* isolate = Isolate::GetCurrent();
- uv_unref(isolate->loop_);
-
- return Undefined();
-}
-
-
-void Isolate::OnMessage(IsolateMessage* msg, void* arg) {
- HandleScope scope;
-
- Isolate* self = static_cast<Isolate*>(arg);
- NODE_ISOLATE_CHECK(self);
-
- Buffer* buf = Buffer::New(msg->data_.buffer_, msg->data_.size_,
- IsolateMessage::Free, msg);
-
- int argc = 1;
- Handle<Value> argv[2] = {
- buf->handle_
- };
-
- if (msg->flags & ISOLATEMESSAGE_SHARED_STREAM) {
- // Instantiate the client javascript object and handle.
- Local<Object> pending_obj = TCPWrap::Instantiate();
-
- // Unwrap the client javascript object.
- assert(pending_obj->InternalFieldCount() > 0);
- TCPWrap* pending_wrap =
- static_cast<TCPWrap*>(pending_obj->GetPointerFromInternalField(0));
-
- int r = uv_import(pending_wrap->GetStream(), &msg->shared_stream_info_);
- assert(r == 0);
-
- argv[1] = pending_obj;
- argc++;
- }
-
- MakeCallback(self->globals_.process, "_onmessage", argc, argv);
-}
-
-
-void Isolate::Initialize() {
- if (initialized) return;
- if (uv_mutex_init(&isolate_mutex)) abort();
- ngx_queue_init(&isolate_list);
- initialized = true;
-}
-
-
-int Isolate::Count() {
- int count;
- uv_mutex_lock(&isolate_mutex);
- count = isolate_count;
- uv_mutex_unlock(&isolate_mutex);
- return count;
-}
-
-
-Isolate::Isolate() {
- send_channel_ = NULL; // set (and deleted) by the parent isolate
- recv_channel_ = NULL;
-
- uv_mutex_lock(&isolate_mutex);
- assert(initialized && "node::Isolate::Initialize() hasn't been called");
- ngx_queue_insert_tail(&isolate_list, &isolate_list_);
- isolate_count++;
- id_ = ++id;
- uv_mutex_unlock(&isolate_mutex);
-
- if (id_ == 1) {
- loop_ = uv_default_loop();
- } else {
- loop_ = uv_loop_new();
- // Artificially ref the isolate loop so that the child
- // isolate stays alive by default. process.exit will
- // unref the loop (see Isolate::Unref).
- uv_ref(loop_);
- }
-
- debug_state = kNone;
- debugger_instance = NULL;
-
- ngx_queue_init(&at_exit_callbacks_);
-
- v8_isolate_ = v8::Isolate::New();
- assert(v8_isolate_->GetData() == NULL);
- v8_isolate_->SetData(this);
-
- globals_init_ = false;
-}
-
-
-Isolate::~Isolate() {
- if (!argv_) return;
- for (size_t i = 0; argv_[i]; ++i) delete[] argv_[i];
- delete[] argv_;
-}
-
-
-struct globals* Isolate::Globals() {
- return &globals_;
-}
-
-
-void Isolate::AtExit(AtExitCallback callback, void* arg) {
- struct AtExitCallbackInfo* it = new AtExitCallbackInfo;
-
- //NODE_ISOLATE_CHECK(this);
-
- it->callback_ = callback;
- it->arg_ = arg;
-
- ngx_queue_insert_head(&at_exit_callbacks_, &it->queue_);
-}
-
-
-void Isolate::Enter() {
- v8_isolate_->Enter();
-
- if (v8_context_.IsEmpty()) {
- v8_context_ = Context::New();
- }
- v8_context_->Enter();
-
- if (!globals_init_) {
- globals_init_ = true;
- globals_init(&globals_);
- }
-
- NODE_ISOLATE_CHECK(this);
-}
-
-
-void Isolate::Exit() {
- NODE_ISOLATE_CHECK(this);
- v8_context_->Exit();
- v8_isolate_->Exit();
-}
-
-
-void Isolate::Dispose() {
- NODE_ISOLATE_CHECK(this);
-
- while (!ngx_queue_empty(&at_exit_callbacks_)) {
- ngx_queue_t* q = ngx_queue_head(&at_exit_callbacks_);
- ngx_queue_remove(q);
-
- AtExitCallbackInfo* it = ngx_queue_data(q, AtExitCallbackInfo, queue_);
- it->callback_(it->arg_);
-
- delete it;
- }
-
- assert(v8_context_->InContext());
- v8_context_->Exit();
- v8_context_.Clear();
- v8_context_.Dispose();
-
- v8_isolate_->Exit();
- v8_isolate_->Dispose();
- v8_isolate_ = NULL;
-
- uv_mutex_lock(&isolate_mutex);
- isolate_count--;
- ngx_queue_remove(&isolate_list_);
- assert(isolate_count >= 0);
- assert((isolate_count == 0 && ngx_queue_empty(&isolate_list))
- || (isolate_count > 0 && !ngx_queue_empty(&isolate_list)));
- uv_mutex_unlock(&isolate_mutex);
-}
-
-
-struct IsolateWrap: public ObjectWrap {
-public:
- IsolateWrap(Isolate* parent_isolate) {
- parent_isolate_ = parent_isolate;
-
- uv_loop_t* parent_loop = parent_isolate->GetLoop();
- recv_channel_ = new IsolateChannel(
- parent_loop, IsolateWrap::OnMessage, this);
-
- isolate_ = new Isolate;
- send_channel_ = new IsolateChannel(
- isolate_->loop_, Isolate::OnMessage, isolate_);
-
- isolate_->send_channel_ = recv_channel_;
- isolate_->recv_channel_ = send_channel_;
-
- // TODO this could be folded into the regular channel
- uv_async_init(parent_loop, &child_exit_, AfterChildExit);
- isolate_->AtExit(AtChildExit, this);
-
- HandleScope scope;
- Local<ObjectTemplate> tpl = ObjectTemplate::New();
- tpl->SetInternalFieldCount(1);
-
- Local<Object> obj = tpl->NewInstance();
- Wrap(obj);
- Ref(); // unref'd when the child isolate exits
-
- obj->Set(String::NewSymbol("tid"),
- Integer::New(isolate_->id_));
-
- obj->Set(String::NewSymbol("send"),
- FunctionTemplate::New(Send)->GetFunction());
- }
-
- ~IsolateWrap() {
- delete isolate_;
- delete recv_channel_;
- delete send_channel_;
- }
-
- Isolate* GetIsolate() {
- return isolate_;
- }
-
-private:
- // runs in the child thread
- static void AtChildExit(void* arg) {
- IsolateWrap* self = static_cast<IsolateWrap*>(arg);
- uv_async_send(&self->child_exit_);
- }
-
- // runs in the parent thread
- static void AfterChildExit(uv_async_t* handle, int status) {
- IsolateWrap* self = container_of(handle, IsolateWrap, child_exit_);
- self->OnExit();
- }
-
- void OnExit() {
- if (uv_thread_join(&isolate_->tid_)) abort();
- uv_close(reinterpret_cast<uv_handle_t*>(&child_exit_), NULL);
- MakeCallback(handle_, "onexit", 0, NULL);
- Unref(); // child is dead, it's safe to GC the JS object now
- }
-
- static void OnMessage(IsolateMessage* msg, void* arg) {
- IsolateWrap* self = static_cast<IsolateWrap*>(arg);
- self->OnMessage(msg);
- }
-
- void OnMessage(IsolateMessage* msg) {
- NODE_ISOLATE_CHECK(parent_isolate_);
- HandleScope scope;
- Buffer* buf = Buffer::New(
- msg->data_.buffer_, msg->data_.size_, IsolateMessage::Free, msg);
-
- int argc = 1;
- Handle<Value> argv[2] = {
- buf->handle_
- };
-
- if (msg->flags & ISOLATEMESSAGE_SHARED_STREAM) {
- // Instantiate the client javascript object and handle.
- Local<Object> pending_obj = TCPWrap::Instantiate();
-
- // Unwrap the client javascript object.
- assert(pending_obj->InternalFieldCount() > 0);
- TCPWrap* pending_wrap =
- static_cast<TCPWrap*>(pending_obj->GetPointerFromInternalField(0));
-
- int r = uv_import(pending_wrap->GetStream(), &msg->shared_stream_info_);
- assert(r == 0);
-
- argv[1] = pending_obj;
- argc++;
- }
-
- MakeCallback(handle_, "onmessage", argc, argv);
- }
-
- // TODO merge with Isolate::Send(), it's almost identical
- static Handle<Value> Send(const Arguments& args) {
- HandleScope scope;
- IsolateWrap* self = Unwrap<IsolateWrap>(args.This());
- assert(Buffer::HasInstance(args[0]));
-
- Local<Object> obj = args[0]->ToObject();
- const char* data = Buffer::Data(obj);
- size_t size = Buffer::Length(obj);
-
- IsolateMessage* msg;
-
- if (args[1]->IsObject()) {
- uv_stream_info_t stream_info;
-
- Local<Object> send_stream_obj = args[1]->ToObject();
- assert(send_stream_obj->InternalFieldCount() > 0);
- StreamWrap* send_stream_wrap = static_cast<StreamWrap*>(
- send_stream_obj->GetPointerFromInternalField(0));
- uv_stream_t* send_stream = send_stream_wrap->GetStream();
- int r = uv_export(send_stream, &stream_info);
- assert(r == 0);
- msg = new IsolateMessage(data, size, &stream_info);
- } else {
- msg = new IsolateMessage(data, size, NULL);
- }
-
- self->send_channel_->Send(msg);
- return Undefined();
- }
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(IsolateWrap);
- Isolate* isolate_;
- Isolate* parent_isolate_;
- IsolateChannel* send_channel_;
- IsolateChannel* recv_channel_;
- uv_async_t child_exit_; // side effect: keeps the parent's event loop alive
- // until the child exits
-};
-
-
-static void RunIsolate(void* arg) {
- Isolate* isolate = static_cast<Isolate*>(arg);
- isolate->Enter();
- StartThread(isolate, isolate->argc_, isolate->argv_);
- isolate->Dispose();
-}
-
-
-static Handle<Value> CreateIsolate(const Arguments& args) {
- HandleScope scope;
-
- assert(args[0]->IsArray());
-
- Local<Array> argv = args[0].As<Array>();
- assert(argv->Length() >= 2);
-
- Isolate* current_isolate = node::Isolate::GetCurrent();
- IsolateWrap* wrap = new IsolateWrap(current_isolate);
- Isolate* isolate = wrap->GetIsolate();
-
- // Copy over arguments into isolate
- isolate->argc_ = argv->Length();
- isolate->argv_ = new char*[isolate->argc_ + 1];
- for (int i = 0; i < isolate->argc_; ++i) {
- String::Utf8Value str(argv->Get(i));
- size_t size = 1 + strlen(*str);
- isolate->argv_[i] = new char[size];
- memcpy(isolate->argv_[i], *str, size);
- }
- isolate->argv_[isolate->argc_] = NULL;
-
- // If options object was provided
- if (args.Length() > 1) {
- Local<Object> options = args[1].As<Object>();
- Local<Value> opt_debug = options->Get(String::New("debug"));
- Local<Value> opt_debug_brk = options->Get(String::New("debugBrk"));
-
- // Handle .debug = true case
- if (opt_debug->IsFunction()) {
- isolate->debug_state = opt_debug_brk->IsTrue() ?
- Isolate::kDebugBrk
- :
- Isolate::kDebug;
- isolate->debugger_instance = IsolateDebugger::New(opt_debug);
- }
- }
-
- if (uv_thread_create(&isolate->tid_, RunIsolate, isolate))
- return Null(); // wrap is collected by the GC
- else
- return wrap->handle_;
-}
-
-
-static Handle<Value> CountIsolate(const Arguments& args) {
- HandleScope scope;
- return scope.Close(Integer::New(Isolate::Count()));
-}
-
-
-void InitIsolates(Handle<Object> target) {
- HandleScope scope;
- NODE_SET_METHOD(target, "create", CreateIsolate);
- NODE_SET_METHOD(target, "count", CountIsolate);
-
- IsolateDebugger::Initialize();
-}
-
-
-class IsolateDebuggerMessage {
- public:
- IsolateDebugger* d_;
- uint16_t* value_;
- int len_;
-
- IsolateDebuggerMessage(IsolateDebugger* d, uint16_t* value, int len) {
- d_ = d;
- value_ = new uint16_t[len];
- len_ = len;
- memcpy(value_, value, len * sizeof(value_[0]));
- }
-
- ~IsolateDebuggerMessage() {
- delete[] value_;
- }
-};
-
-
-void IsolateDebugger::Initialize() {
- HandleScope scope;
-
- Local<FunctionTemplate> t = FunctionTemplate::New(IsolateDebugger::New);
- isolate_debugger_constructor = Persistent<FunctionTemplate>::New(t);
-
- t->InstanceTemplate()->SetInternalFieldCount(1);
- t->SetClassName(String::NewSymbol("IsolateDebugger"));
-
- NODE_SET_PROTOTYPE_METHOD(t, "write", IsolateDebugger::Write);
-}
-
-
-IsolateDebugger::IsolateDebugger(Handle<Value> init) {
- debuggee_ = NULL;
- initialized_ = false;
- host_ = Isolate::GetCurrent();
- host_loop_ = host_->GetLoop();
- init_callback_fn_ = Persistent<Value>::New(init);
-
- // Init async handle to invoke js callback once
- // debugger will be initialized
- uv_async_init(host_loop_,
- &init_callback_,
- IsolateDebugger::In