@@ -100,6 +100,8 @@ Persistent<String> process_symbol;
100100Persistent<String> domain_symbol;
101101
102102static Persistent<Object> process;
103+ static Persistent<Function> process_tickWDCallback;
104+ static Persistent<Function> process_tickFromSpinner;
103105static Persistent<Function> process_tickCallback;
104106
105107static Persistent<String> exports_symbol;
@@ -174,20 +176,19 @@ static void Tick(void) {
174176
175177 HandleScope scope;
176178
177- if (tick_callback_sym.IsEmpty ()) {
178- // Lazily set the symbol
179- tick_callback_sym = NODE_PSYMBOL (" _tickCallback" );
179+ if (process_tickFromSpinner.IsEmpty ()) {
180+ Local<Value> cb_v = process->Get (String::New (" _tickFromSpinner" ));
181+ if (!cb_v->IsFunction ()) {
182+ fprintf (stderr, " process._tickFromSpinner assigned to non-function\n " );
183+ abort ();
184+ }
185+ Local<Function> cb = cb_v.As <Function>();
186+ process_tickFromSpinner = Persistent<Function>::New (cb);
180187 }
181188
182- Local<Value> cb_v = process->Get (tick_callback_sym);
183- if (!cb_v->IsFunction ()) return ;
184- Local<Function> cb = Local<Function>::Cast (cb_v);
185-
186189 TryCatch try_catch;
187190
188- // Let the tick callback know that this is coming from the spinner
189- Handle<Value> argv[] = { True (node_isolate) };
190- cb->Call (process, ARRAY_SIZE (argv), argv);
191+ process_tickFromSpinner->Call (process, 0 , NULL );
191192
192193 if (try_catch.HasCaught ()) {
193194 FatalException (try_catch);
@@ -903,46 +904,23 @@ Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate> t,
903904}
904905
905906
906- // MakeCallback may only be made directly off the event loop.
907- // That is there can be no JavaScript stack frames underneath it.
908- // (Is there any way to assert that?)
909- //
910- // Maybe make this a method of a node::Handle super class
911- //
912- Handle<Value>
913- MakeCallback (const Handle<Object> object,
914- const char * method,
915- int argc,
916- Handle<Value> argv[]) {
917- HandleScope scope;
918-
919- Handle<Value> ret =
920- MakeCallback (object, String::NewSymbol (method), argc, argv);
921-
922- return scope.Close (ret);
923- }
924-
925907Handle<Value>
926- MakeCallback (const Handle<Object> object,
927- const Handle<String> symbol ,
908+ MCWithDomain (const Handle<Object> object,
909+ const Handle<Function> callback ,
928910 int argc,
929911 Handle<Value> argv[]) {
930- HandleScope scope;
931-
932- Local<Value> callback_v = object->Get (symbol);
933- if (!callback_v->IsFunction ()) {
934- String::Utf8Value method (symbol);
935- // XXX: If the object has a domain attached, handle it there?
936- // At least, would be good to get *some* sort of indication
937- // of how we got here, even if it's not catchable.
938- fprintf (stderr, " Non-function in MakeCallback. method = %s\n " , *method);
939- abort ();
912+ // lazy load _tickWDCallback
913+ if (process_tickWDCallback.IsEmpty ()) {
914+ Local<Value> cb_v = process->Get (String::New (" _tickWDCallback" ));
915+ if (!cb_v->IsFunction ()) {
916+ fprintf (stderr, " process._tickWDCallback assigned to non-function\n " );
917+ abort ();
918+ }
919+ Local<Function> cb = cb_v.As <Function>();
920+ process_tickWDCallback = Persistent<Function>::New (cb);
940921 }
941922
942- // TODO Hook for long stack traces to be made here.
943-
944- TryCatch try_catch;
945-
923+ // lazy load domain specific symbols
946924 if (enter_symbol.IsEmpty ()) {
947925 enter_symbol = NODE_PSYMBOL (" enter" );
948926 exit_symbol = NODE_PSYMBOL (" exit" );
@@ -953,40 +931,71 @@ MakeCallback(const Handle<Object> object,
953931 Local<Object> domain;
954932 Local<Function> enter;
955933 Local<Function> exit;
956- if (!domain_v-> IsUndefined ()) {
957- domain = domain_v-> ToObject () ;
958- if (domain-> Get (disposed_symbol)-> BooleanValue ()) {
959- // domain has been disposed of.
960- return Undefined (node_isolate );
961- }
962- enter = Local<Function>:: Cast ( domain-> Get (enter_symbol));
963- enter-> Call (domain, 0 , NULL );
934+
935+ TryCatch try_catch ;
936+
937+ domain = domain_v-> ToObject ();
938+ assert (!domain. IsEmpty () );
939+ if (domain-> Get (disposed_symbol)-> IsTrue ()) {
940+ // domain has been disposed of.
941+ return Undefined (node_isolate );
964942 }
943+ enter = Local<Function>::Cast (domain->Get (enter_symbol));
944+ assert (!enter.IsEmpty ());
945+ enter->Call (domain, 0 , NULL );
965946
966947 if (try_catch.HasCaught ()) {
967948 FatalException (try_catch);
968949 return Undefined (node_isolate);
969950 }
970951
971- Local<Function> callback = Local<Function>::Cast (callback_v);
972952 Local<Value> ret = callback->Call (object, argc, argv);
973953
974954 if (try_catch.HasCaught ()) {
975955 FatalException (try_catch);
976956 return Undefined (node_isolate);
977957 }
978958
979- if (!domain_v->IsUndefined ()) {
980- exit = Local<Function>::Cast (domain->Get (exit_symbol));
981- exit->Call (domain, 0 , NULL );
959+ exit = Local<Function>::Cast (domain->Get (exit_symbol));
960+ assert (!exit.IsEmpty ());
961+ exit->Call (domain, 0 , NULL );
962+
963+ if (try_catch.HasCaught ()) {
964+ FatalException (try_catch);
965+ return Undefined (node_isolate);
982966 }
983967
968+ // process nextTicks after call
969+ process_tickWDCallback->Call (process, 0 , NULL );
970+
984971 if (try_catch.HasCaught ()) {
985972 FatalException (try_catch);
986973 return Undefined (node_isolate);
987974 }
988975
989- // process nextTicks after every time we get called.
976+ return ret;
977+ }
978+
979+
980+ Handle<Value>
981+ MakeCallback (const Handle<Object> object,
982+ const Handle<String> symbol,
983+ int argc,
984+ Handle<Value> argv[]) {
985+ HandleScope scope;
986+
987+ Local<Value> callback_v = object->Get (symbol);
988+ if (!callback_v->IsFunction ()) {
989+ String::Utf8Value method (symbol);
990+ fprintf (stderr, " Non-function in MakeCallback. method = %s\n " , *method);
991+ abort ();
992+ }
993+
994+ Local<Function> callback = Local<Function>::Cast (callback_v);
995+
996+ // TODO Hook for long stack traces to be made here.
997+
998+ // lazy load no domain next tick callbacks
990999 if (process_tickCallback.IsEmpty ()) {
9911000 Local<Value> cb_v = process->Get (String::New (" _tickCallback" ));
9921001 if (!cb_v->IsFunction ()) {
@@ -996,7 +1005,24 @@ MakeCallback(const Handle<Object> object,
9961005 Local<Function> cb = cb_v.As <Function>();
9971006 process_tickCallback = Persistent<Function>::New (cb);
9981007 }
999- process_tickCallback->Call (process, NULL , 0 );
1008+
1009+ // has domain, off with you
1010+ if (object->Has (domain_symbol) &&
1011+ !object->Get (domain_symbol)->IsNull () &&
1012+ !object->Get (domain_symbol)->IsUndefined ())
1013+ return scope.Close (MCWithDomain (object, callback, argc, argv));
1014+
1015+ TryCatch try_catch;
1016+
1017+ Local<Value> ret = callback->Call (object, argc, argv);
1018+
1019+ if (try_catch.HasCaught ()) {
1020+ FatalException (try_catch);
1021+ return Undefined (node_isolate);
1022+ }
1023+
1024+ // process nextTicks after call
1025+ process_tickCallback->Call (process, 0 , NULL );
10001026
10011027 if (try_catch.HasCaught ()) {
10021028 FatalException (try_catch);
@@ -1007,6 +1033,20 @@ MakeCallback(const Handle<Object> object,
10071033}
10081034
10091035
1036+ Handle<Value>
1037+ MakeCallback (const Handle<Object> object,
1038+ const char * method,
1039+ int argc,
1040+ Handle<Value> argv[]) {
1041+ HandleScope scope;
1042+
1043+ Handle<Value> ret =
1044+ MakeCallback (object, String::NewSymbol (method), argc, argv);
1045+
1046+ return scope.Close (ret);
1047+ }
1048+
1049+
10101050void SetErrno (uv_err_t err) {
10111051 HandleScope scope;
10121052
0 commit comments