@ -26,7 +26,6 @@
// of the startup process, so many dependencies are invoked lazily.
// of the startup process, so many dependencies are invoked lazily.
( function ( process ) {
( function ( process ) {
this . global = this ;
this . global = this ;
var _ errorHandler ;
function startup ( ) {
function startup ( ) {
var EventEmitter = NativeModule . require ( 'events' ) . EventEmitter ;
var EventEmitter = NativeModule . require ( 'events' ) . EventEmitter ;
@ -40,6 +39,9 @@
process . EventEmitter = EventEmitter ; // process.EventEmitter is deprecated
process . EventEmitter = EventEmitter ; // process.EventEmitter is deprecated
// Setup the tracing module
NativeModule . require ( 'tracing' ) . _ nodeInitialization ( process ) ;
// do this good and early, since it handles errors.
// do this good and early, since it handles errors.
startup . processFatal ( ) ;
startup . processFatal ( ) ;
@ -47,7 +49,6 @@
startup . globalTimeouts ( ) ;
startup . globalTimeouts ( ) ;
startup . globalConsole ( ) ;
startup . globalConsole ( ) ;
startup . processAsyncListener ( ) ;
startup . processAssert ( ) ;
startup . processAssert ( ) ;
startup . processConfig ( ) ;
startup . processConfig ( ) ;
startup . processNextTick ( ) ;
startup . processNextTick ( ) ;
@ -220,6 +221,11 @@
} ;
} ;
startup . processFatal = function ( ) {
startup . processFatal = function ( ) {
var tracing = NativeModule . require ( 'tracing' ) ;
var _ errorHandler = tracing . _ errorHandler ;
// Cleanup
delete tracing . _ errorHandler ;
process . _ fatalException = function ( er ) {
process . _ fatalException = function ( er ) {
// First run through error handlers from asyncListener.
// First run through error handlers from asyncListener.
var caught = _ errorHandler ( er ) ;
var caught = _ errorHandler ( er ) ;
@ -255,339 +261,6 @@
} ;
} ;
} ;
} ;
startup . processAsyncListener = function ( ) {
// new Array() is used here because it is more efficient for sparse
// arrays. Please *do not* change these to simple bracket notation.
// Track the active queue of AsyncListeners that have been added.
var asyncQueue = new Array ( ) ;
// Keep the stack of all contexts that have been loaded in the
// execution chain of asynchronous events.
var contextStack = new Array ( ) ;
var currentContext = undefined ;
// Incremental uid for new AsyncListener instances.
var alUid = 0 ;
// Stateful flags shared with Environment for quick JS/C++
// communication.
var asyncFlags = { } ;
// Prevent accidentally suppressed thrown errors from before/after.
var inAsyncTick = false ;
// To prevent infinite recursion when an error handler also throws
// flag when an error is currenly being handled.
var inErrorTick = false ;
// Needs to be the same as src/env.h
var kHasListener = 0 ;
var kWatchedProviders = 1 ;
// Flags to determine what async listeners are available.
var HAS_CREATE_AL = 1 << 0 ;
var HAS_BEFORE_AL = 1 << 1 ;
var HAS_AFTER_AL = 1 << 2 ;
var HAS_ERROR_AL = 1 << 3 ;
// _errorHandler is scoped so it's also accessible by _fatalException.
_ errorHandler = errorHandler ;
// Needs to be accessible from lib/timers.js so they know when async
// listeners are currently in queue. They'll be cleaned up once
// references there are made.
process . _ asyncFlags = asyncFlags ;
process . _ runAsyncQueue = runAsyncQueue ;
process . _ loadAsyncQueue = loadAsyncQueue ;
process . _ unloadAsyncQueue = unloadAsyncQueue ;
// Public API.
process . createAsyncListener = createAsyncListener ;
process . addAsyncListener = addAsyncListener ;
process . removeAsyncListener = removeAsyncListener ;
// Setup shared objects/callbacks with native layer.
process . _ setupAsyncListener ( asyncFlags ,
runAsyncQueue ,
loadAsyncQueue ,
unloadAsyncQueue ) ;
// Load the currently executing context as the current context, and
// create a new asyncQueue that can receive any added queue items
// during the executing of the callback.
function loadContext ( ctx ) {
contextStack . push ( currentContext ) ;
currentContext = ctx ;
asyncFlags [ kHasListener ] = 1 ;
}
function unloadContext ( ) {
currentContext = contextStack . pop ( ) ;
if ( currentContext === undefined && asyncQueue . length === 0 )
asyncFlags [ kHasListener ] = 0 ;
}
// Run all the async listeners attached when an asynchronous event is
// instantiated.
function runAsyncQueue ( context ) {
var queue = new Array ( ) ;
var data = new Array ( ) ;
var ccQueue , i , item , queueItem , value ;
context . _ asyncQueue = queue ;
context . _ asyncData = data ;
context . _ asyncFlags = 0 ;
inAsyncTick = true ;
// First run through all callbacks in the currentContext. These may
// add new AsyncListeners to the asyncQueue during execution. Hence
// why they need to be evaluated first.
if ( currentContext ) {
ccQueue = currentContext . _ asyncQueue ;
context . _ asyncFlags |= currentContext . _ asyncFlags ;
for ( i = 0 ; i < ccQueue . length ; i ++ ) {
queueItem = ccQueue [ i ] ;
queue [ queue . length ] = queueItem ;
if ( ( queueItem . callback_flags & HAS_CREATE_AL ) === 0 ) {
data [ queueItem . uid ] = queueItem . data ;
continue ;
}
value = queueItem . create ( queueItem . data ) ;
data [ queueItem . uid ] = ( value === undefined ) ? queueItem . data : value ;
}
}
// Then run through all items in the asyncQueue
if ( asyncQueue ) {
for ( i = 0 ; i < asyncQueue . length ; i ++ ) {
queueItem = asyncQueue [ i ] ;
// Quick way to check if an AL instance with the same uid was
// already run from currentContext.
if ( data [ queueItem . uid ] !== undefined )
continue ;
queue [ queue . length ] = queueItem ;
context . _ asyncFlags |= queueItem . callback_flags ;
if ( ( queueItem . callback_flags & HAS_CREATE_AL ) === 0 ) {
data [ queueItem . uid ] = queueItem . data ;
continue ;
}
value = queueItem . create ( queueItem . data ) ;
data [ queueItem . uid ] = ( value === undefined ) ? queueItem . data : value ;
}
}
inAsyncTick = false ;
}
// Load the AsyncListener queue attached to context and run all
// "before" callbacks, if they exist.
function loadAsyncQueue ( context ) {
loadContext ( context ) ;
if ( ( context . _ asyncFlags & HAS_BEFORE_AL ) === 0 )
return ;
var queue = context . _ asyncQueue ;
var data = context . _ asyncData ;
var i , queueItem ;
inAsyncTick = true ;
for ( i = 0 ; i < queue . length ; i ++ ) {
queueItem = queue [ i ] ;
if ( ( queueItem . callback_flags & HAS_BEFORE_AL ) > 0 )
queueItem . before ( context , data [ queueItem . uid ] ) ;
}
inAsyncTick = false ;
}
// Unload the AsyncListener queue attached to context and run all
// "after" callbacks, if they exist.
function unloadAsyncQueue ( context ) {
if ( ( context . _ asyncFlags & HAS_AFTER_AL ) === 0 ) {
unloadContext ( ) ;
return ;
}
var queue = context . _ asyncQueue ;
var data = context . _ asyncData ;
var i , queueItem ;
inAsyncTick = true ;
for ( i = 0 ; i < queue . length ; i ++ ) {
queueItem = queue [ i ] ;
if ( ( queueItem . callback_flags & HAS_AFTER_AL ) > 0 )
queueItem . after ( context , data [ queueItem . uid ] ) ;
}
inAsyncTick = false ;
unloadContext ( ) ;
}
// Handle errors that are thrown while in the context of an
// AsyncListener. If an error is thrown from an AsyncListener
// callback error handlers will be called once more to report
// the error, then the application will die forcefully.
function errorHandler ( er ) {
if ( inErrorTick )
return false ;
var handled = false ;
var i , queueItem , threw ;
inErrorTick = true ;
// First process error callbacks from the current context.
if ( currentContext && ( currentContext . _ asyncFlags & HAS_ERROR_AL ) > 0 ) {
var queue = currentContext . _ asyncQueue ;
var data = currentContext . _ asyncData ;
for ( i = 0 ; i < queue . length ; i ++ ) {
queueItem = queue [ i ] ;
if ( ( queueItem . callback_flags & HAS_ERROR_AL ) === 0 )
continue ;
try {
threw = true ;
// While it would be possible to pass in currentContext, if
// the error is thrown from the "create" callback then there's
// a chance the object hasn't been fully constructed.
handled = queueItem . error ( data [ queueItem . uid ] , er ) || handled ;
threw = false ;
} finally {
// If the error callback thew then die quickly. Only allow the
// exit events to be processed.
if ( threw ) {
process . _ exiting = true ;
process . emit ( 'exit' , 1 ) ;
}
}
}
}
// Now process callbacks from any existing queue.
if ( asyncQueue ) {
for ( i = 0 ; i < asyncQueue . length ; i ++ ) {
queueItem = asyncQueue [ i ] ;
if ( ( queueItem . callback_flags & HAS_ERROR_AL ) === 0 ||
( data && data [ queueItem . uid ] !== undefined ) )
continue ;
try {
threw = true ;
handled = queueItem . error ( queueItem . data , er ) || handled ;
threw = false ;
} finally {
// If the error callback thew then die quickly. Only allow the
// exit events to be processed.
if ( threw ) {
process . _ exiting = true ;
process . emit ( 'exit' , 1 ) ;
}
}
}
}
inErrorTick = false ;
unloadContext ( ) ;
// TODO(trevnorris): If the error was handled, should the after callbacks
// be fired anyways?
return handled && ! inAsyncTick ;
}
// Instance function of an AsyncListener object.
function AsyncListenerInst ( callbacks , data ) {
if ( typeof callbacks . create === 'function' ) {
this . create = callbacks . create ;
this . callback_flags |= HAS_CREATE_AL ;
}
if ( typeof callbacks . before === 'function' ) {
this . before = callbacks . before ;
this . callback_flags |= HAS_BEFORE_AL ;
}
if ( typeof callbacks . after === 'function' ) {
this . after = callbacks . after ;
this . callback_flags |= HAS_AFTER_AL ;
}
if ( typeof callbacks . error === 'function' ) {
this . error = callbacks . error ;
this . callback_flags |= HAS_ERROR_AL ;
}
this . uid = ++ alUid ;
this . data = data === undefined ? null : data ;
}
AsyncListenerInst . prototype . create = undefined ;
AsyncListenerInst . prototype . before = undefined ;
AsyncListenerInst . prototype . after = undefined ;
AsyncListenerInst . prototype . error = undefined ;
AsyncListenerInst . prototype . data = undefined ;
AsyncListenerInst . prototype . uid = 0 ;
AsyncListenerInst . prototype . callback_flags = 0 ;
// Create new async listener object. Useful when instantiating a new
// object and want the listener instance, but not add it to the stack.
// If an existing AsyncListenerInst is passed then any new "data" is
// ignored.
function createAsyncListener ( callbacks , data ) {
if ( typeof callbacks !== 'object' || callbacks == null )
throw new TypeError ( 'callbacks argument must be an object' ) ;
if ( callbacks instanceof AsyncListenerInst )
return callbacks ;
else
return new AsyncListenerInst ( callbacks , data ) ;
}
// Add a listener to the current queue.
function addAsyncListener ( callbacks , data ) {
// Fast track if a new AsyncListenerInst has to be created.
if ( ! ( callbacks instanceof AsyncListenerInst ) ) {
callbacks = createAsyncListener ( callbacks , data ) ;
asyncQueue . push ( callbacks ) ;
asyncFlags [ kHasListener ] = 1 ;
return callbacks ;
}
var inQueue = false ;
// The asyncQueue will be small. Probably always <= 3 items.
for ( var i = 0 ; i < asyncQueue . length ; i ++ ) {
if ( callbacks === asyncQueue [ i ] ) {
inQueue = true ;
break ;
}
}
// Make sure the callback doesn't already exist in the queue.
if ( ! inQueue ) {
asyncQueue . push ( callbacks ) ;
asyncFlags [ kHasListener ] = 1 ;
}
return callbacks ;
}
// Remove listener from the current queue. Though this will not remove
// the listener from the current context. So callback propagation will
// continue.
function removeAsyncListener ( obj ) {
for ( var i = 0 ; i < asyncQueue . length ; i ++ ) {
if ( obj === asyncQueue [ i ] ) {
asyncQueue . splice ( i , 1 ) ;
break ;
}
}
if ( asyncQueue . length > 0 || currentContext !== undefined )
asyncFlags [ kHasListener ] = 1 ;
else
asyncFlags [ kHasListener ] = 0 ;
}
} ;
var assert ;
var assert ;
startup . processAssert = function ( ) {
startup . processAssert = function ( ) {
assert = process . assert = function ( x , msg ) {
assert = process . assert = function ( x , msg ) {
@ -611,11 +284,12 @@
} ;
} ;
startup . processNextTick = function ( ) {
startup . processNextTick = function ( ) {
var tracing = NativeModule . require ( 'tracing' ) ;
var nextTickQueue = [ ] ;
var nextTickQueue = [ ] ;
var asyncFlags = process . _ asyncFlags ;
var asyncFlags = tracing . _ asyncFlags ;
var _ runAsyncQueue = process . _ runAsyncQueue ;
var _ runAsyncQueue = tracing . _ runAsyncQueue ;
var _ loadAsyncQueue = process . _ loadAsyncQueue ;
var _ loadAsyncQueue = tracing . _ loadAsyncQueue ;
var _ unloadAsyncQueue = process . _ unloadAsyncQueue ;
var _ unloadAsyncQueue = tracing . _ unloadAsyncQueue ;
// This tickInfo thing is used so that the C++ code in src/node.cc
// This tickInfo thing is used so that the C++ code in src/node.cc
// can have easy accesss to our nextTick state, and avoid unnecessary
// can have easy accesss to our nextTick state, and avoid unnecessary