exit program on top level exceptions

(also lots of reorg.)
This commit is contained in:
Ryan 2009-03-04 00:31:37 +01:00
Родитель a890b67406
Коммит e02b71ebe8
9 изменённых файлов: 95 добавлений и 90 удалений

Просмотреть файл

@ -3,7 +3,8 @@ function encode(data) {
return chunk.length.toString(16) + "\r\n" + chunk + "\r\n"; return chunk.length.toString(16) + "\r\n" + chunk + "\r\n";
} }
var server = new HTTP.Server("localhost", 8000); var port = 8000;
var server = new HTTP.Server("localhost", port);
server.onRequest = function (request) { server.onRequest = function (request) {
@ -21,8 +22,12 @@ server.onRequest = function (request) {
request.respond("Content-Type: text/plain\r\n"); request.respond("Content-Type: text/plain\r\n");
request.respond("Transfer-Encoding: chunked\r\n"); request.respond("Transfer-Encoding: chunked\r\n");
request.respond("\r\n"); request.respond("\r\n");
}; };
log("Running at http://localhost:" + port + "/");
/* /*
server.close(); server.close();
*/ */

74
node.cc
Просмотреть файл

@ -1,4 +1,4 @@
#include <oi.h> #include "node.h"
#include "node_tcp.h" #include "node_tcp.h"
#include "node_http.h" #include "node_http.h"
@ -6,24 +6,37 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <string> #include <string>
#include <list> #include <list>
#include <map> #include <map>
#include <v8.h>
using namespace v8; using namespace v8;
using namespace std; using namespace std;
static struct ev_loop *loop; static int exit_code = 0;
static Persistent<Context> context; void
static Persistent<Function> process_; node_fatal_exception (TryCatch &try_catch)
{
HandleScope handle_scope;
Local<Message> message = try_catch.Message();
String::Utf8Value error(try_catch.Exception());
fprintf( stderr
, "Uncaught Exception. line %d '%s'\n\n"
, try_catch.Message()->GetLineNumber()
, *error
);
ev_unloop(node_loop(), EVUNLOOP_ALL);
exit_code = 1;
}
// Reads a file into a v8 string. // Reads a file into a v8 string.
static Handle<String> ReadFile static Handle<String>
( const string& name ReadFile (const string& name)
)
{ {
FILE* file = fopen(name.c_str(), "rb"); FILE* file = fopen(name.c_str(), "rb");
if (file == NULL) return Handle<String>(); if (file == NULL) return Handle<String>();
@ -44,12 +57,8 @@ static Handle<String> ReadFile
return result; return result;
} }
static void ParseOptions static void
( int argc ParseOptions (int argc, char* argv[], map<string, string>& options, string* file)
, char* argv[]
, map<string, string>& options
, string* file
)
{ {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
string arg = argv[i]; string arg = argv[i];
@ -64,9 +73,8 @@ static void ParseOptions
} }
} }
static bool compile static bool
( Handle<String> script compile (Handle<String> script)
)
{ {
HandleScope handle_scope; HandleScope handle_scope;
@ -99,26 +107,30 @@ static bool compile
return true; return true;
} }
static Handle<Value> LogCallback static Handle<Value>
( const Arguments& args LogCallback (const Arguments& args)
)
{ {
if (args.Length() < 1) return v8::Undefined(); if (args.Length() < 1) return v8::Undefined();
HandleScope scope; HandleScope scope;
Handle<Value> arg = args[0]; Handle<Value> arg = args[0];
String::Utf8Value value(arg); String::Utf8Value value(arg);
printf("Logged: %s\n", *value); printf("%s\n", *value);
fflush(stdout); fflush(stdout);
return v8::Undefined(); return v8::Undefined();
} }
static void
OnFatalError (const char* location, const char* message)
{
fprintf(stderr, "Fatal error. %s %s\n", location, message);
ev_unloop(node_loop(), EVUNLOOP_ALL);
}
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
loop = ev_default_loop(0);
map<string, string> options; map<string, string> options;
string file; string file;
ParseOptions(argc, argv, options, &file); ParseOptions(argc, argv, options, &file);
@ -133,24 +145,26 @@ main (int argc, char *argv[])
return 1; return 1;
} }
context = Context::New(NULL, ObjectTemplate::New()); Persistent<Context> context = Context::New(NULL, ObjectTemplate::New());
Context::Scope context_scope(context); Context::Scope context_scope(context);
Local<Object> g = Context::GetCurrent()->Global(); Local<Object> g = Context::GetCurrent()->Global();
g->Set( String::New("log"), FunctionTemplate::New(LogCallback)->GetFunction()); g->Set( String::New("log"), FunctionTemplate::New(LogCallback)->GetFunction());
g->Set( String::New("TCP"), node_tcp_initialize(loop));
g->Set( String::New("HTTP"), node_http_initialize(loop));
node_timer_initialize(g, loop); node_tcp_initialize(g);
node_http_initialize(g);
node_timer_initialize(g);
V8::SetFatalErrorHandler(OnFatalError);
// Compile and run the script // Compile and run the script
if (!compile(source)) if (!compile(source))
return 1; return 1;
ev_loop(loop, 0); ev_loop(node_loop(), 0);
context.Dispose(); context.Dispose();
return 0; return exit_code;
} }

11
node.h Normal file
Просмотреть файл

@ -0,0 +1,11 @@
#ifndef node_h
#define node_h
#include <ev.h>
#include <v8.h>
void node_fatal_exception (v8::TryCatch &try_catch);
#define node_loop() ev_default_loop(0)
#endif // node_h

Просмотреть файл

@ -1,4 +1,5 @@
#include "node_http.h" #include "node_http.h"
#include "node.h"
#include <oi_socket.h> #include <oi_socket.h>
#include <ebb_request_parser.h> #include <ebb_request_parser.h>
@ -6,13 +7,10 @@
#include <string> #include <string>
#include <list> #include <list>
#include <v8.h>
using namespace v8; using namespace v8;
using namespace std; using namespace std;
static Persistent<ObjectTemplate> request_template; static Persistent<ObjectTemplate> request_template;
static struct ev_loop *loop;
// globals // globals
static Persistent<String> path_str; static Persistent<String> path_str;
@ -226,10 +224,9 @@ on_headers_complete (ebb_request *req)
const int argc = 1; const int argc = 1;
Handle<Value> argv[argc] = { js_request }; Handle<Value> argv[argc] = { js_request };
Handle<Value> r = request->connection.js_onRequest->Call(Context::GetCurrent()->Global(), argc, argv); Handle<Value> r = request->connection.js_onRequest->Call(Context::GetCurrent()->Global(), argc, argv);
if (r.IsEmpty()) {
String::Utf8Value error(try_catch.Exception()); if(try_catch.HasCaught())
printf("error: %s\n", *error); node_fatal_exception(try_catch);
}
} }
static void static void
@ -346,10 +343,8 @@ HttpRequest::MakeBodyCallback (const char *base, size_t length)
Handle<Value> result = onBody->Call(js_object, argc, argv); Handle<Value> result = onBody->Call(js_object, argc, argv);
if (result.IsEmpty()) { if(try_catch.HasCaught())
String::Utf8Value error(try_catch.Exception()); node_fatal_exception(try_catch);
printf("error: %s\n", *error);
}
} }
Local<Object> Local<Object>
@ -490,7 +485,7 @@ Server::Start(struct addrinfo *servinfo)
{ {
int r = oi_server_listen(&server, servinfo); int r = oi_server_listen(&server, servinfo);
if(r == 0) if(r == 0)
oi_server_attach(&server, loop); oi_server_attach(&server, node_loop());
return r; return r;
} }
@ -541,25 +536,23 @@ server_constructor (const Arguments& args)
if (r != 0) if (r != 0)
return Undefined(); // XXX raise error? return Undefined(); // XXX raise error?
printf("Running at http://localhost:%s/\n", *port);
return args.This(); return args.This();
} }
Handle<Object> void
node_http_initialize (struct ev_loop *_loop) node_http_initialize (Handle<Object> target)
{ {
HandleScope scope; HandleScope scope;
loop = _loop;
Local<Object> http = Object::New(); Local<Object> http = Object::New();
target->Set (String::NewSymbol("HTTP"), http);
Local<FunctionTemplate> server_t = FunctionTemplate::New(server_constructor); Local<FunctionTemplate> server_t = FunctionTemplate::New(server_constructor);
server_t->InstanceTemplate()->SetInternalFieldCount(1); server_t->InstanceTemplate()->SetInternalFieldCount(1);
http->Set(String::New("Server"), server_t->GetFunction()); http->Set(String::New("Server"), server_t->GetFunction());
path_str = Persistent<String>::New( String::NewSymbol("path") ); path_str = Persistent<String>::New( String::NewSymbol("path") );
uri_str = Persistent<String>::New( String::NewSymbol("uri") ); uri_str = Persistent<String>::New( String::NewSymbol("uri") );
query_string_str = Persistent<String>::New( String::NewSymbol("query_string") ); query_string_str = Persistent<String>::New( String::NewSymbol("query_string") );
@ -585,6 +578,4 @@ node_http_initialize (struct ev_loop *_loop)
put_str = Persistent<String>::New( String::New("PUT") ); put_str = Persistent<String>::New( String::New("PUT") );
trace_str = Persistent<String>::New( String::New("TRACE") ); trace_str = Persistent<String>::New( String::New("TRACE") );
unlock_str = Persistent<String>::New( String::New("UNLOCK") ); unlock_str = Persistent<String>::New( String::New("UNLOCK") );
return scope.Close(http);
} }

Просмотреть файл

@ -2,10 +2,7 @@
#define node_http_h #define node_http_h
#include <v8.h> #include <v8.h>
#include <ev.h>
using namespace v8; void node_http_initialize (v8::Handle<v8::Object> target);
Handle<Object> node_http_initialize (struct ev_loop *);
#endif #endif

Просмотреть файл

@ -1,4 +1,5 @@
#include "node_tcp.h" #include "node_tcp.h"
#include "node.h"
#include <oi_socket.h> #include <oi_socket.h>
#include <oi_async.h> #include <oi_async.h>
@ -7,6 +8,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
using namespace v8;
/* /*
@ -50,8 +52,6 @@ static struct addrinfo tcp_hints =
/* ai_next */ , 0 /* ai_next */ , 0
}; };
static struct ev_loop *loop;
class TCPClient { class TCPClient {
public: public:
oi_task resolve_task; oi_task resolve_task;
@ -110,8 +110,7 @@ static void resolve_done
client->socket.data = client; client->socket.data = client;
oi_socket_connect (&client->socket, client->address); oi_socket_connect (&client->socket, client->address);
oi_socket_attach (&client->socket, loop); oi_socket_attach (&client->socket, node_loop());
freeaddrinfo(client->address); freeaddrinfo(client->address);
client->address = NULL; client->address = NULL;
@ -166,21 +165,17 @@ static Handle<Value> Connect
oi_async_submit (&thread_pool, &client->resolve_task); oi_async_submit (&thread_pool, &client->resolve_task);
} }
Handle<Object> node_tcp_initialize void
( struct ev_loop *_loop node_tcp_initialize (Handle<Object> target)
)
{ {
loop = _loop;
oi_async_init(&thread_pool); oi_async_init(&thread_pool);
oi_async_attach(loop, &thread_pool); oi_async_attach(node_loop(), &thread_pool);
HandleScope scope; HandleScope scope;
Local<Object> t = Object::New(); Local<Object> tcp = Object::New();
target->Set(String::NewSymbol("TCP"), tcp);
t->Set(String::New("connect"), FunctionTemplate::New(Connect)->GetFunction()); tcp->Set(String::NewSymbol("connect"), FunctionTemplate::New(Connect)->GetFunction());
return scope.Close(t);
} }

Просмотреть файл

@ -2,10 +2,7 @@
#define node_tcp_h #define node_tcp_h
#include <v8.h> #include <v8.h>
#include <ev.h>
using namespace v8; void node_tcp_initialize (v8::Handle<v8::Object> target);
Handle<Object> node_tcp_initialize (struct ev_loop *);
#endif #endif

Просмотреть файл

@ -1,7 +1,7 @@
#include <ev.h> #include "node.h"
#include <v8.h> #include "node_timer.h"
using namespace v8; using namespace v8;
static struct ev_loop *loop;
class Timer { class Timer {
public: public:
@ -37,12 +37,12 @@ Timer::Timer (Handle<Function> _callback, int _argc, Handle<Value> _argv[], ev_t
ev_timer_init (&watcher, onTimeout, after, repeat); ev_timer_init (&watcher, onTimeout, after, repeat);
watcher.data = this; watcher.data = this;
ev_timer_start (loop, &watcher); ev_timer_start (node_loop(), &watcher);
} }
Timer::~Timer () Timer::~Timer ()
{ {
ev_timer_stop (loop, &watcher); ev_timer_stop (node_loop(), &watcher);
callback.Dispose(); callback.Dispose();
@ -57,11 +57,10 @@ Timer::CallCallback ()
TryCatch try_catch; TryCatch try_catch;
Handle<Value> r = callback->Call (Context::GetCurrent()->Global(), argc, argv); callback->Call (Context::GetCurrent()->Global(), argc, argv);
if (r.IsEmpty()) {
String::Utf8Value error(try_catch.Exception()); if(try_catch.HasCaught())
printf("timer callback error: %s\n", *error); node_fatal_exception(try_catch);
}
} }
Local<External> Local<External>
@ -166,10 +165,8 @@ static Handle<Value> setInterval
} }
void void
node_timer_initialize (Handle<Object> target, struct ev_loop *_loop) node_timer_initialize (Handle<Object> target)
{ {
loop = _loop;
HandleScope scope; HandleScope scope;
target->Set ( String::New("setTimeout") target->Set ( String::New("setTimeout")

Просмотреть файл

@ -1,10 +1,8 @@
#ifndef node_timer_h #ifndef node_timer_h
#define node_timer_h #define node_timer_h
#include <ev.h>
#include <v8.h> #include <v8.h>
using namespace v8;
void node_timer_initialize (Handle<Object> target, struct ev_loop *_loop); void node_timer_initialize (v8::Handle<v8::Object> target);
#endif // node_timer_h #endif // node_timer_h