@@ -105,6 +105,8 @@ Persistent<String> domain_symbol;
105105// declared in node_internals.h
106106Persistent<Object> process;
107107
108+ static Persistent<Array> domains_stack;
109+
108110static Persistent<Function> process_tickFromSpinner;
109111static Persistent<Function> process_tickCallback;
110112
@@ -126,6 +128,8 @@ static Persistent<String> exit_symbol;
126128static Persistent<String> disposed_symbol;
127129
128130static Persistent<String> emitting_toplevel_domain_error_symbol;
131+ static Persistent<String> _events_symbol;
132+ static Persistent<String> error_symbol;
129133
130134static bool print_eval = false ;
131135static bool force_repl = false ;
@@ -904,25 +908,83 @@ Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate> t,
904908 return scope.Close (t->GetFunction ()->NewInstance (argc, argv));
905909}
906910
907- static bool IsDomainActive () {
908- if (domain_symbol.IsEmpty ())
909- domain_symbol = NODE_PSYMBOL (" domain" );
911+ static bool DomainHasErrorHandler (const Local<Object>& domain) {
912+ HandleScope scope;
913+
914+ if (_events_symbol.IsEmpty ())
915+ _events_symbol = NODE_PSYMBOL (" _events" );
916+
917+ Local<Value> domain_event_listeners_v = domain->Get (_events_symbol);
918+ if (!domain_event_listeners_v->IsObject ())
919+ return false ;
920+
921+ Local<Object> domain_event_listeners_o =
922+ domain_event_listeners_v->ToObject ();
923+
924+ if (domain_event_listeners_o->IsNull ())
925+ return false ;
926+
927+ if (error_symbol.IsEmpty ())
928+ error_symbol = NODE_PSYMBOL (" error" );
929+
930+ Local<Value> domain_error_listeners_v =
931+ domain_event_listeners_o->Get (error_symbol);
932+
933+ if (domain_error_listeners_v->IsFunction () ||
934+ (domain_error_listeners_v->IsArray () &&
935+ domain_error_listeners_v.As <Array>()->Length () > 0 ))
936+ return true ;
937+
938+ return false ;
939+ }
940+
941+ static bool TopDomainHasErrorHandler () {
942+ HandleScope scope;
943+
944+ if (!using_domains)
945+ return false ;
910946
911- Local<Value> domain_v = process->Get (domain_symbol);
947+ Local<Array> domains_stack_array = Local<Array>::New (domains_stack);
948+ if (domains_stack_array->Length () == 0 )
949+ return false ;
912950
913- return domain_v->IsObject ();
951+ uint32_t domains_stack_length = domains_stack_array->Length ();
952+ if (domains_stack_length <= 0 )
953+ return false ;
954+
955+ Local<Value> domain_v = domains_stack_array->Get (domains_stack_length - 1 );
956+ if (domain_v->IsNull ())
957+ return false ;
958+
959+ Local<Object> domain = domain_v->ToObject ();
960+ if (domain->IsNull ())
961+ return false ;
962+
963+ if (DomainHasErrorHandler (domain))
964+ return true ;
965+
966+ return false ;
914967}
915968
916969bool ShouldAbortOnUncaughtException () {
917970 Local<Value> emitting_toplevel_domain_error_v =
918971 process->Get (emitting_toplevel_domain_error_symbol);
919- return !IsDomainActive () || emitting_toplevel_domain_error_v->BooleanValue ();
972+
973+ return emitting_toplevel_domain_error_v->BooleanValue () ||
974+ !TopDomainHasErrorHandler ();
920975}
921976
922977Handle<Value> UsingDomains (const Arguments& args) {
923978 HandleScope scope;
979+
924980 if (using_domains)
925981 return scope.Close (Undefined ());
982+
983+ if (!args[0 ]->IsArray ()) {
984+ fprintf (stderr, " domains stack must be an array\n " );
985+ abort ();
986+ }
987+
926988 using_domains = true ;
927989 Local<Value> tdc_v = process->Get (String::New (" _tickDomainCallback" ));
928990 Local<Value> ndt_v = process->Get (String::New (" _nextDomainTick" ));
@@ -934,6 +996,9 @@ Handle<Value> UsingDomains(const Arguments& args) {
934996 fprintf (stderr, " process._nextDomainTick assigned to non-function\n " );
935997 abort ();
936998 }
999+
1000+ domains_stack = Persistent<Array>::New (args[0 ].As <Array>());
1001+
9371002 Local<Function> tdc = tdc_v.As <Function>();
9381003 Local<Function> ndt = ndt_v.As <Function>();
9391004 process->Set (String::New (" _tickCallback" ), tdc);
@@ -2449,7 +2514,10 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
24492514 process->Set (String::NewSymbol (" _tickInfoBox" ), info_box);
24502515
24512516 // pre-set _events object for faster emit checks
2452- process->Set (String::NewSymbol (" _events" ), Object::New ());
2517+ if (_events_symbol.IsEmpty ())
2518+ _events_symbol = NODE_PSYMBOL (" _events" );
2519+
2520+ process->Set (_events_symbol, Object::New ());
24532521
24542522 if (emitting_toplevel_domain_error_symbol.IsEmpty ())
24552523 emitting_toplevel_domain_error_symbol =
0 commit comments