@@ -106,6 +106,8 @@ Persistent<String> domain_symbol;
106
106
// declared in node_internals.h
107
107
Persistent<Object> process;
108
108
109
+ static Persistent<Array> domains_stack;
110
+
109
111
static Persistent<Function> process_tickFromSpinner;
110
112
static Persistent<Function> process_tickCallback;
111
113
@@ -127,6 +129,8 @@ static Persistent<String> exit_symbol;
127
129
static Persistent<String> disposed_symbol;
128
130
129
131
static Persistent<String> emitting_toplevel_domain_error_symbol;
132
+ static Persistent<String> _events_symbol;
133
+ static Persistent<String> error_symbol;
130
134
131
135
static bool print_eval = false ;
132
136
static bool force_repl = false ;
@@ -905,25 +909,77 @@ Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate> t,
905
909
return scope.Close (t->GetFunction ()->NewInstance (argc, argv));
906
910
}
907
911
908
- static bool IsDomainActive () {
909
- if (domain_symbol.IsEmpty ())
910
- domain_symbol = NODE_PSYMBOL (" domain" );
912
+ static bool DomainHasErrorHandler (const Local<Object>& domain) {
913
+ HandleScope scope;
914
+
915
+ if (_events_symbol.IsEmpty ())
916
+ _events_symbol = NODE_PSYMBOL (" _events" );
917
+
918
+ Local<Value> domain_event_listeners_v = domain->Get (_events_symbol);
919
+ if (!domain_event_listeners_v->IsObject ())
920
+ return false ;
921
+
922
+ Local<Object> domain_event_listeners_o =
923
+ domain_event_listeners_v.As <Object>();
924
+
925
+ if (error_symbol.IsEmpty ())
926
+ error_symbol = NODE_PSYMBOL (" error" );
927
+
928
+ Local<Value> domain_error_listeners_v =
929
+ domain_event_listeners_o->Get (error_symbol);
930
+
931
+ if (domain_error_listeners_v->IsFunction () ||
932
+ (domain_error_listeners_v->IsArray () &&
933
+ domain_error_listeners_v.As <Array>()->Length () > 0 ))
934
+ return true ;
935
+
936
+ return false ;
937
+ }
938
+
939
+ static bool TopDomainHasErrorHandler () {
940
+ HandleScope scope;
941
+
942
+ if (!using_domains)
943
+ return false ;
911
944
912
- Local<Value> domain_v = process->Get (domain_symbol);
945
+ Local<Array> domains_stack_array = Local<Array>::New (domains_stack);
946
+ if (domains_stack_array->Length () == 0 )
947
+ return false ;
913
948
914
- return domain_v->IsObject ();
949
+ uint32_t domains_stack_length = domains_stack_array->Length ();
950
+ if (domains_stack_length == 0 )
951
+ return false ;
952
+
953
+ Local<Value> domain_v = domains_stack_array->Get (domains_stack_length - 1 );
954
+ if (!domain_v->IsObject ())
955
+ return false ;
956
+
957
+ Local<Object> domain = domain_v.As <Object>();
958
+ if (DomainHasErrorHandler (domain))
959
+ return true ;
960
+
961
+ return false ;
915
962
}
916
963
917
964
bool ShouldAbortOnUncaughtException () {
918
965
Local<Value> emitting_toplevel_domain_error_v =
919
966
process->Get (emitting_toplevel_domain_error_symbol);
920
- return !IsDomainActive () || emitting_toplevel_domain_error_v->BooleanValue ();
967
+
968
+ return emitting_toplevel_domain_error_v->BooleanValue () ||
969
+ !TopDomainHasErrorHandler ();
921
970
}
922
971
923
972
Handle<Value> UsingDomains (const Arguments& args) {
924
973
HandleScope scope;
974
+
925
975
if (using_domains)
926
976
return scope.Close (Undefined ());
977
+
978
+ if (!args[0 ]->IsArray ()) {
979
+ fprintf (stderr, " domains stack must be an array\n " );
980
+ abort ();
981
+ }
982
+
927
983
using_domains = true ;
928
984
Local<Value> tdc_v = process->Get (String::New (" _tickDomainCallback" ));
929
985
Local<Value> ndt_v = process->Get (String::New (" _nextDomainTick" ));
@@ -935,6 +991,9 @@ Handle<Value> UsingDomains(const Arguments& args) {
935
991
fprintf (stderr, " process._nextDomainTick assigned to non-function\n " );
936
992
abort ();
937
993
}
994
+
995
+ domains_stack = Persistent<Array>::New (args[0 ].As <Array>());
996
+
938
997
Local<Function> tdc = tdc_v.As <Function>();
939
998
Local<Function> ndt = ndt_v.As <Function>();
940
999
process->Set (String::New (" _tickCallback" ), tdc);
@@ -2460,7 +2519,10 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
2460
2519
process->Set (String::NewSymbol (" _tickInfoBox" ), info_box);
2461
2520
2462
2521
// pre-set _events object for faster emit checks
2463
- process->Set (String::NewSymbol (" _events" ), Object::New ());
2522
+ if (_events_symbol.IsEmpty ())
2523
+ _events_symbol = NODE_PSYMBOL (" _events" );
2524
+
2525
+ process->Set (_events_symbol, Object::New ());
2464
2526
2465
2527
if (emitting_toplevel_domain_error_symbol.IsEmpty ())
2466
2528
emitting_toplevel_domain_error_symbol =
0 commit comments