@@ -105,6 +105,8 @@ Persistent<String> domain_symbol;
105
105
// declared in node_internals.h
106
106
Persistent<Object> process;
107
107
108
+ static Persistent<Array> domains_stack;
109
+
108
110
static Persistent<Function> process_tickFromSpinner;
109
111
static Persistent<Function> process_tickCallback;
110
112
@@ -126,6 +128,8 @@ static Persistent<String> exit_symbol;
126
128
static Persistent<String> disposed_symbol;
127
129
128
130
static Persistent<String> emitting_toplevel_domain_error_symbol;
131
+ static Persistent<String> _events_symbol;
132
+ static Persistent<String> error_symbol;
129
133
130
134
static bool print_eval = false ;
131
135
static bool force_repl = false ;
@@ -904,25 +908,82 @@ Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate> t,
904
908
return scope.Close (t->GetFunction ()->NewInstance (argc, argv));
905
909
}
906
910
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 domainsStackHasErrorHandler () {
942
+ HandleScope scope;
943
+
944
+ if (!using_domains)
945
+ return false ;
910
946
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 ;
912
950
913
- return domain_v->IsObject ();
951
+ uint32_t domains_stack_length = domains_stack_array->Length ();
952
+ for (int i = domains_stack_length - 1 ; i >= 0 ; --i) {
953
+ Local<Value> domain_v = domains_stack_array->Get (i);
954
+ if (domain_v->IsNull ())
955
+ return false ;
956
+
957
+ Local<Object> domain = domain_v->ToObject ();
958
+ if (domain->IsNull ())
959
+ return false ;
960
+
961
+ if (domainHasErrorHandler (domain))
962
+ return true ;
963
+ }
964
+
965
+ return false ;
914
966
}
915
967
916
968
bool ShouldAbortOnUncaughtException () {
917
969
Local<Value> emitting_toplevel_domain_error_v =
918
970
process->Get (emitting_toplevel_domain_error_symbol);
919
- return !IsDomainActive () || emitting_toplevel_domain_error_v->BooleanValue ();
971
+
972
+ return emitting_toplevel_domain_error_v->BooleanValue () ||
973
+ !domainsStackHasErrorHandler ();
920
974
}
921
975
922
976
Handle<Value> UsingDomains (const Arguments& args) {
923
977
HandleScope scope;
978
+
924
979
if (using_domains)
925
980
return scope.Close (Undefined ());
981
+
982
+ if (!args[0 ]->IsArray ()) {
983
+ fprintf (stderr, " domains stack must be an array\n " );
984
+ abort ();
985
+ }
986
+
926
987
using_domains = true ;
927
988
Local<Value> tdc_v = process->Get (String::New (" _tickDomainCallback" ));
928
989
Local<Value> ndt_v = process->Get (String::New (" _nextDomainTick" ));
@@ -934,6 +995,9 @@ Handle<Value> UsingDomains(const Arguments& args) {
934
995
fprintf (stderr, " process._nextDomainTick assigned to non-function\n " );
935
996
abort ();
936
997
}
998
+
999
+ domains_stack = Persistent<Array>::New (args[0 ].As <Array>());
1000
+
937
1001
Local<Function> tdc = tdc_v.As <Function>();
938
1002
Local<Function> ndt = ndt_v.As <Function>();
939
1003
process->Set (String::New (" _tickCallback" ), tdc);
@@ -2449,7 +2513,10 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
2449
2513
process->Set (String::NewSymbol (" _tickInfoBox" ), info_box);
2450
2514
2451
2515
// pre-set _events object for faster emit checks
2452
- process->Set (String::NewSymbol (" _events" ), Object::New ());
2516
+ if (_events_symbol.IsEmpty ())
2517
+ _events_symbol = NODE_PSYMBOL (" _events" );
2518
+
2519
+ process->Set (_events_symbol, Object::New ());
2453
2520
2454
2521
if (emitting_toplevel_domain_error_symbol.IsEmpty ())
2455
2522
emitting_toplevel_domain_error_symbol =
0 commit comments