src: move AsyncListener from process to tracing
The AsyncListener API has been moved into the "tracing" module in order to keep the process object free from unnecessary clutter. Signed-off-by: Timothy J Fontaine <tjfontaine@gmail.com>
This commit is contained in:
parent
d9e1e4c661
commit
6cbfcdad46
@ -684,219 +684,4 @@ a diff reading, useful for benchmarks and measuring intervals:
|
|||||||
// benchmark took 1000000527 nanoseconds
|
// benchmark took 1000000527 nanoseconds
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
|
||||||
## Async Listeners
|
|
||||||
|
|
||||||
<!-- type=misc -->
|
|
||||||
|
|
||||||
Stability: 1 - Experimental
|
|
||||||
|
|
||||||
The `AsyncListener` API is the JavaScript interface for the `AsyncWrap`
|
|
||||||
class which allows developers to be notified about key events in the
|
|
||||||
lifetime of an asynchronous event. Node performs a lot of asynchronous
|
|
||||||
events internally, and significant use of this API may have a
|
|
||||||
**significant performance impact** on your application.
|
|
||||||
|
|
||||||
|
|
||||||
## process.createAsyncListener(callbacksObj[, userData])
|
|
||||||
|
|
||||||
* `callbacksObj` {Object} Contains optional callbacks that will fire at
|
|
||||||
specific times in the life cycle of the asynchronous event.
|
|
||||||
* `userData` {Value} a value that will be passed to all callbacks.
|
|
||||||
|
|
||||||
Returns a constructed `AsyncListener` object.
|
|
||||||
|
|
||||||
To begin capturing asynchronous events pass either the `callbacksObj` or
|
|
||||||
and existing `AsyncListener` instance to [`process.addAsyncListener()`][].
|
|
||||||
The same `AsyncListener` instance can only be added once to the active
|
|
||||||
queue, and subsequent attempts to add the instance will be ignored.
|
|
||||||
|
|
||||||
To stop capturing pass the `AsyncListener` instance to
|
|
||||||
[`process.removeAsyncListener()`][]. This does _not_ mean the
|
|
||||||
`AsyncListener` previously added will stop triggering callbacks. Once
|
|
||||||
attached to an asynchronous event it will persist with the lifetime of the
|
|
||||||
asynchronous call stack.
|
|
||||||
|
|
||||||
Explanation of function parameters:
|
|
||||||
|
|
||||||
|
|
||||||
`callbacksObj`: An `Object` which may contain three optional fields:
|
|
||||||
|
|
||||||
* `create(userData)`: A `Function` called when an asynchronous
|
|
||||||
event is instantiated. If a `Value` is returned then it will be attached
|
|
||||||
to the event and overwrite any value that had been passed to
|
|
||||||
`process.createAsyncListener()`'s `userData` argument. If an initial
|
|
||||||
`userData` was passed when created, then `create()` will
|
|
||||||
receive that as a function argument.
|
|
||||||
|
|
||||||
* `before(context, userData)`: A `Function` that is called immediately
|
|
||||||
before the asynchronous callback is about to run. It will be passed both
|
|
||||||
the `context` (i.e. `this`) of the calling function and the `userData`
|
|
||||||
either returned from `create()` or passed during construction (if
|
|
||||||
either occurred).
|
|
||||||
|
|
||||||
* `after(context, userData)`: A `Function` called immediately after
|
|
||||||
the asynchronous event's callback has run. Note this will not be called
|
|
||||||
if the callback throws and the error is not handled.
|
|
||||||
|
|
||||||
* `error(userData, error)`: A `Function` called if the event's
|
|
||||||
callback threw. If this registered callback returns `true` then Node will
|
|
||||||
assume the error has been properly handled and resume execution normally.
|
|
||||||
When multiple `error()` callbacks have been registered only **one** of
|
|
||||||
those callbacks needs to return `true` for `AsyncListener` to accept that
|
|
||||||
the error has been handled, but all `error()` callbacks will always be run.
|
|
||||||
|
|
||||||
`userData`: A `Value` (i.e. anything) that will be, by default,
|
|
||||||
attached to all new event instances. This will be overwritten if a `Value`
|
|
||||||
is returned by `create()`.
|
|
||||||
|
|
||||||
Here is an example of overwriting the `userData`:
|
|
||||||
|
|
||||||
process.createAsyncListener({
|
|
||||||
create: function listener(value) {
|
|
||||||
// value === true
|
|
||||||
return false;
|
|
||||||
}, {
|
|
||||||
before: function before(context, value) {
|
|
||||||
// value === false
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
**Note:** The [EventEmitter][], while used to emit status of an asynchronous
|
|
||||||
event, is not itself asynchronous. So `create()` will not fire when
|
|
||||||
an event is added, and `before`/`after` will not fire when emitted
|
|
||||||
callbacks are called.
|
|
||||||
|
|
||||||
|
|
||||||
## process.addAsyncListener(callbacksObj[, userData])
|
|
||||||
## process.addAsyncListener(asyncListener)
|
|
||||||
|
|
||||||
Returns a constructed `AsyncListener` object and immediately adds it to
|
|
||||||
the listening queue to begin capturing asynchronous events.
|
|
||||||
|
|
||||||
Function parameters can either be the same as
|
|
||||||
[`process.createAsyncListener()`][], or a constructed `AsyncListener`
|
|
||||||
object.
|
|
||||||
|
|
||||||
Example usage for capturing errors:
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var cntr = 0;
|
|
||||||
var key = process.addAsyncListener({
|
|
||||||
create: function onCreate() {
|
|
||||||
return { uid: cntr++ };
|
|
||||||
},
|
|
||||||
before: function onBefore(context, storage) {
|
|
||||||
// Write directly to stdout or we'll enter a recursive loop
|
|
||||||
fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n');
|
|
||||||
},
|
|
||||||
after: function onAfter(context, storage) {
|
|
||||||
fs.writeSync(1, 'uid: ' + storage.uid + ' ran\n');
|
|
||||||
},
|
|
||||||
error: function onError(storage, err) {
|
|
||||||
// Handle known errors
|
|
||||||
if (err.message === 'everything is fine') {
|
|
||||||
fs.writeSync(1, 'handled error just threw:\n');
|
|
||||||
fs.writeSync(1, err.stack + '\n');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
throw new Error('everything is fine');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// uid: 0 is about to run
|
|
||||||
// handled error just threw:
|
|
||||||
// Error: really, it's ok
|
|
||||||
// at /tmp/test2.js:27:9
|
|
||||||
// at process._tickCallback (node.js:583:11)
|
|
||||||
// at Function.Module.runMain (module.js:492:11)
|
|
||||||
// at startup (node.js:123:16)
|
|
||||||
// at node.js:1012:3
|
|
||||||
|
|
||||||
## process.removeAsyncListener(asyncListener)
|
|
||||||
|
|
||||||
Removes the `AsyncListener` from the listening queue.
|
|
||||||
|
|
||||||
Removing the `AsyncListener` from the active queue does _not_ mean the
|
|
||||||
`asyncListener` callbacks will cease to fire on the events they've been
|
|
||||||
registered. Subsequently, any asynchronous events fired during the
|
|
||||||
execution of a callback will also have the same `asyncListener` callbacks
|
|
||||||
attached for future execution. For example:
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var key = process.createAsyncListener({
|
|
||||||
create: function asyncListener() {
|
|
||||||
// Write directly to stdout or we'll enter a recursive loop
|
|
||||||
fs.writeSync(1, 'You summoned me?\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// We want to begin capturing async events some time in the future.
|
|
||||||
setTimeout(function() {
|
|
||||||
process.addAsyncListener(key);
|
|
||||||
|
|
||||||
// Perform a few additional async events.
|
|
||||||
setTimeout(function() {
|
|
||||||
setImmediate(function() {
|
|
||||||
process.nextTick(function() { });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Removing the listener doesn't mean to stop capturing events that
|
|
||||||
// have already been added.
|
|
||||||
process.removeAsyncListener(key);
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// You summoned me?
|
|
||||||
// You summoned me?
|
|
||||||
// You summoned me?
|
|
||||||
// You summoned me?
|
|
||||||
|
|
||||||
The fact that we logged 4 asynchronous events is an implementation detail
|
|
||||||
of Node's [Timers][].
|
|
||||||
|
|
||||||
To stop capturing from a specific asynchronous event stack
|
|
||||||
`process.removeAsyncListener()` must be called from within the call
|
|
||||||
stack itself. For example:
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var key = process.createAsyncListener({
|
|
||||||
create: function asyncListener() {
|
|
||||||
// Write directly to stdout or we'll enter a recursive loop
|
|
||||||
fs.writeSync(1, 'You summoned me?\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// We want to begin capturing async events some time in the future.
|
|
||||||
setTimeout(function() {
|
|
||||||
process.addAsyncListener(key);
|
|
||||||
|
|
||||||
// Perform a few additional async events.
|
|
||||||
setImmediate(function() {
|
|
||||||
// Stop capturing from this call stack.
|
|
||||||
process.removeAsyncListener(key);
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// You summoned me?
|
|
||||||
|
|
||||||
The user must be explicit and always pass the `AsyncListener` they wish
|
|
||||||
to remove. It is not possible to simply remove all listeners at once.
|
|
||||||
|
|
||||||
|
|
||||||
[EventEmitter]: events.html#events_class_events_eventemitter
|
[EventEmitter]: events.html#events_class_events_eventemitter
|
||||||
[Timers]: timers.html
|
|
||||||
[`process.createAsyncListener()`]: #process_process_createasynclistener_asynclistener_callbacksobj_storagevalue
|
|
||||||
[`process.addAsyncListener()`]: #process_process_addasynclistener_asynclistener
|
|
||||||
[`process.removeAsyncListener()`]: #process_process_removeasynclistener_asynclistener
|
|
||||||
|
@ -58,4 +58,216 @@ Returns an object with the following properties
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# Async Listeners
|
||||||
|
|
||||||
|
The `AsyncListener` API is the JavaScript interface for the `AsyncWrap`
|
||||||
|
class which allows developers to be notified about key events in the
|
||||||
|
lifetime of an asynchronous event. Node performs a lot of asynchronous
|
||||||
|
events internally, and significant use of this API may have a
|
||||||
|
**significant performance impact** on your application.
|
||||||
|
|
||||||
|
|
||||||
|
## tracing.createAsyncListener(callbacksObj[, userData])
|
||||||
|
|
||||||
|
* `callbacksObj` {Object} Contains optional callbacks that will fire at
|
||||||
|
specific times in the life cycle of the asynchronous event.
|
||||||
|
* `userData` {Value} a value that will be passed to all callbacks.
|
||||||
|
|
||||||
|
Returns a constructed `AsyncListener` object.
|
||||||
|
|
||||||
|
To begin capturing asynchronous events pass either the `callbacksObj` or
|
||||||
|
pass an existing `AsyncListener` instance to [`tracing.addAsyncListener()`][].
|
||||||
|
The same `AsyncListener` instance can only be added once to the active
|
||||||
|
queue, and subsequent attempts to add the instance will be ignored.
|
||||||
|
|
||||||
|
To stop capturing pass the `AsyncListener` instance to
|
||||||
|
[`tracing.removeAsyncListener()`][]. This does _not_ mean the
|
||||||
|
`AsyncListener` previously added will stop triggering callbacks. Once
|
||||||
|
attached to an asynchronous event it will persist with the lifetime of the
|
||||||
|
asynchronous call stack.
|
||||||
|
|
||||||
|
Explanation of function parameters:
|
||||||
|
|
||||||
|
|
||||||
|
`callbacksObj`: An `Object` which may contain several optional fields:
|
||||||
|
|
||||||
|
* `create(userData)`: A `Function` called when an asynchronous
|
||||||
|
event is instantiated. If a `Value` is returned then it will be attached
|
||||||
|
to the event and overwrite any value that had been passed to
|
||||||
|
`tracing.createAsyncListener()`'s `userData` argument. If an initial
|
||||||
|
`userData` was passed when created, then `create()` will
|
||||||
|
receive that as a function argument.
|
||||||
|
|
||||||
|
* `before(context, userData)`: A `Function` that is called immediately
|
||||||
|
before the asynchronous callback is about to run. It will be passed both
|
||||||
|
the `context` (i.e. `this`) of the calling function and the `userData`
|
||||||
|
either returned from `create()` or passed during construction (if
|
||||||
|
either occurred).
|
||||||
|
|
||||||
|
* `after(context, userData)`: A `Function` called immediately after
|
||||||
|
the asynchronous event's callback has run. Note this will not be called
|
||||||
|
if the callback throws and the error is not handled.
|
||||||
|
|
||||||
|
* `error(userData, error)`: A `Function` called if the event's
|
||||||
|
callback threw. If this registered callback returns `true` then Node will
|
||||||
|
assume the error has been properly handled and resume execution normally.
|
||||||
|
When multiple `error()` callbacks have been registered only **one** of
|
||||||
|
those callbacks needs to return `true` for `AsyncListener` to accept that
|
||||||
|
the error has been handled, but all `error()` callbacks will always be run.
|
||||||
|
|
||||||
|
`userData`: A `Value` (i.e. anything) that will be, by default,
|
||||||
|
attached to all new event instances. This will be overwritten if a `Value`
|
||||||
|
is returned by `create()`.
|
||||||
|
|
||||||
|
Here is an example of overwriting the `userData`:
|
||||||
|
|
||||||
|
tracing.createAsyncListener({
|
||||||
|
create: function listener(value) {
|
||||||
|
// value === true
|
||||||
|
return false;
|
||||||
|
}, {
|
||||||
|
before: function before(context, value) {
|
||||||
|
// value === false
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
**Note:** The [EventEmitter][], while used to emit status of an asynchronous
|
||||||
|
event, is not itself asynchronous. So `create()` will not fire when
|
||||||
|
an event is added, and `before()`/`after()` will not fire when emitted
|
||||||
|
callbacks are called.
|
||||||
|
|
||||||
|
|
||||||
|
## tracing.addAsyncListener(callbacksObj[, userData])
|
||||||
|
## tracing.addAsyncListener(asyncListener)
|
||||||
|
|
||||||
|
Returns a constructed `AsyncListener` object and immediately adds it to
|
||||||
|
the listening queue to begin capturing asynchronous events.
|
||||||
|
|
||||||
|
Function parameters can either be the same as
|
||||||
|
[`tracing.createAsyncListener()`][], or a constructed `AsyncListener`
|
||||||
|
object.
|
||||||
|
|
||||||
|
Example usage for capturing errors:
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var cntr = 0;
|
||||||
|
var key = tracing.addAsyncListener({
|
||||||
|
create: function onCreate() {
|
||||||
|
return { uid: cntr++ };
|
||||||
|
},
|
||||||
|
before: function onBefore(context, storage) {
|
||||||
|
// Write directly to stdout or we'll enter a recursive loop
|
||||||
|
fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n');
|
||||||
|
},
|
||||||
|
after: function onAfter(context, storage) {
|
||||||
|
fs.writeSync(1, 'uid: ' + storage.uid + ' ran\n');
|
||||||
|
},
|
||||||
|
error: function onError(storage, err) {
|
||||||
|
// Handle known errors
|
||||||
|
if (err.message === 'everything is fine') {
|
||||||
|
// Writing to stderr this time.
|
||||||
|
fs.writeSync(2, 'handled error just threw:\n');
|
||||||
|
fs.writeSync(2, err.stack + '\n');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
process.nextTick(function() {
|
||||||
|
throw new Error('everything is fine');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// uid: 0 is about to run
|
||||||
|
// handled error just threw:
|
||||||
|
// Error: really, it's ok
|
||||||
|
// at /tmp/test2.js:27:9
|
||||||
|
// at process._tickCallback (node.js:583:11)
|
||||||
|
// at Function.Module.runMain (module.js:492:11)
|
||||||
|
// at startup (node.js:123:16)
|
||||||
|
// at node.js:1012:3
|
||||||
|
|
||||||
|
## tracing.removeAsyncListener(asyncListener)
|
||||||
|
|
||||||
|
Removes the `AsyncListener` from the listening queue.
|
||||||
|
|
||||||
|
Removing the `AsyncListener` from the active queue does _not_ mean the
|
||||||
|
`asyncListener` callbacks will cease to fire on the events they've been
|
||||||
|
registered. Subsequently, any asynchronous events fired during the
|
||||||
|
execution of a callback will also have the same `asyncListener` callbacks
|
||||||
|
attached for future execution. For example:
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var key = tracing.createAsyncListener({
|
||||||
|
create: function asyncListener() {
|
||||||
|
// Write directly to stdout or we'll enter a recursive loop
|
||||||
|
fs.writeSync(1, 'You summoned me?\n');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// We want to begin capturing async events some time in the future.
|
||||||
|
setTimeout(function() {
|
||||||
|
tracing.addAsyncListener(key);
|
||||||
|
|
||||||
|
// Perform a few additional async events.
|
||||||
|
setTimeout(function() {
|
||||||
|
setImmediate(function() {
|
||||||
|
process.nextTick(function() { });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Removing the listener doesn't mean to stop capturing events that
|
||||||
|
// have already been added.
|
||||||
|
tracing.removeAsyncListener(key);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// You summoned me?
|
||||||
|
// You summoned me?
|
||||||
|
// You summoned me?
|
||||||
|
// You summoned me?
|
||||||
|
|
||||||
|
The fact that we logged 4 asynchronous events is an implementation detail
|
||||||
|
of Node's [Timers][].
|
||||||
|
|
||||||
|
To stop capturing from a specific asynchronous event stack
|
||||||
|
`tracing.removeAsyncListener()` must be called from within the call
|
||||||
|
stack itself. For example:
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var key = tracing.createAsyncListener({
|
||||||
|
create: function asyncListener() {
|
||||||
|
// Write directly to stdout or we'll enter a recursive loop
|
||||||
|
fs.writeSync(1, 'You summoned me?\n');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// We want to begin capturing async events some time in the future.
|
||||||
|
setTimeout(function() {
|
||||||
|
tracing.addAsyncListener(key);
|
||||||
|
|
||||||
|
// Perform a few additional async events.
|
||||||
|
setImmediate(function() {
|
||||||
|
// Stop capturing from this call stack.
|
||||||
|
tracing.removeAsyncListener(key);
|
||||||
|
|
||||||
|
process.nextTick(function() { });
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// You summoned me?
|
||||||
|
|
||||||
|
The user must be explicit and always pass the `AsyncListener` they wish
|
||||||
|
to remove. It is not possible to simply remove all listeners at once.
|
||||||
|
|
||||||
|
|
||||||
[EventEmitter]: events.html#events_class_events_eventemitter
|
[EventEmitter]: events.html#events_class_events_eventemitter
|
||||||
|
[Timers]: timers.html
|
||||||
|
[`tracing.createAsyncListener()`]: #tracing_tracing_createasynclistener_asynclistener_callbacksobj_storagevalue
|
||||||
|
[`tracing.addAsyncListener()`]: #tracing_tracing_addasynclistener_asynclistener
|
||||||
|
[`tracing.removeAsyncListener()`]: #tracing_tracing_removeasynclistener_asynclistener
|
||||||
|
@ -30,19 +30,20 @@ var TIMEOUT_MAX = 2147483647; // 2^31-1
|
|||||||
|
|
||||||
var debug = require('util').debuglog('timer');
|
var debug = require('util').debuglog('timer');
|
||||||
|
|
||||||
var asyncFlags = process._asyncFlags;
|
var tracing = require('tracing');
|
||||||
var runAsyncQueue = process._runAsyncQueue;
|
var asyncFlags = tracing._asyncFlags;
|
||||||
var loadAsyncQueue = process._loadAsyncQueue;
|
var runAsyncQueue = tracing._runAsyncQueue;
|
||||||
var unloadAsyncQueue = process._unloadAsyncQueue;
|
var loadAsyncQueue = tracing._loadAsyncQueue;
|
||||||
|
var unloadAsyncQueue = tracing._unloadAsyncQueue;
|
||||||
|
|
||||||
// Same as in AsyncListener in env.h
|
// Same as in AsyncListener in env.h
|
||||||
var kHasListener = 0;
|
var kHasListener = 0;
|
||||||
|
|
||||||
// Do a little housekeeping.
|
// Do a little housekeeping.
|
||||||
delete process._asyncFlags;
|
delete tracing._asyncFlags;
|
||||||
delete process._runAsyncQueue;
|
delete tracing._runAsyncQueue;
|
||||||
delete process._loadAsyncQueue;
|
delete tracing._loadAsyncQueue;
|
||||||
delete process._unloadAsyncQueue;
|
delete tracing._unloadAsyncQueue;
|
||||||
|
|
||||||
|
|
||||||
// IDLE TIMEOUTS
|
// IDLE TIMEOUTS
|
||||||
|
357
lib/tracing.js
357
lib/tracing.js
@ -20,7 +20,31 @@
|
|||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
var EventEmitter = require('events');
|
var EventEmitter = require('events');
|
||||||
var binding = process.binding('v8');
|
var v8binding, process;
|
||||||
|
|
||||||
|
// This needs to be loaded early, and before the "process" object is made
|
||||||
|
// global. So allow src/node.js to pass the process object in during
|
||||||
|
// initialization.
|
||||||
|
exports._nodeInitialization = function nodeInitialization(pobj) {
|
||||||
|
process = pobj;
|
||||||
|
v8binding = process.binding('v8');
|
||||||
|
|
||||||
|
// Finish setting up the v8 Object.
|
||||||
|
v8.getHeapStatistics = v8binding.getHeapStatistics;
|
||||||
|
|
||||||
|
// Part of the AsyncListener setup to share objects/callbacks with the
|
||||||
|
// native layer.
|
||||||
|
process._setupAsyncListener(asyncFlags,
|
||||||
|
runAsyncQueue,
|
||||||
|
loadAsyncQueue,
|
||||||
|
unloadAsyncQueue);
|
||||||
|
|
||||||
|
// Do a little housekeeping.
|
||||||
|
delete exports._nodeInitialization;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// v8
|
||||||
|
|
||||||
var v8 = exports.v8 = new EventEmitter();
|
var v8 = exports.v8 = new EventEmitter();
|
||||||
|
|
||||||
@ -32,16 +56,341 @@ function emitGC(before, after) {
|
|||||||
|
|
||||||
v8.on('newListener', function(name) {
|
v8.on('newListener', function(name) {
|
||||||
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
|
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
|
||||||
binding.startGarbageCollectionTracking(emitGC);
|
v8binding.startGarbageCollectionTracking(emitGC);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
v8.on('removeListener', function(name) {
|
v8.on('removeListener', function(name) {
|
||||||
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
|
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
|
||||||
binding.stopGarbageCollectionTracking();
|
v8binding.stopGarbageCollectionTracking();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
v8.getHeapStatistics = binding.getHeapStatistics;
|
// AsyncListener
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
exports._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.
|
||||||
|
exports._asyncFlags = asyncFlags;
|
||||||
|
exports._runAsyncQueue = runAsyncQueue;
|
||||||
|
exports._loadAsyncQueue = loadAsyncQueue;
|
||||||
|
exports._unloadAsyncQueue = unloadAsyncQueue;
|
||||||
|
|
||||||
|
// Public API.
|
||||||
|
exports.createAsyncListener = createAsyncListener;
|
||||||
|
exports.addAsyncListener = addAsyncListener;
|
||||||
|
exports.removeAsyncListener = removeAsyncListener;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
352
src/node.js
352
src/node.js
@ -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
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var active = null;
|
var active = null;
|
||||||
var cntr = 0;
|
var cntr = 0;
|
||||||
@ -49,16 +50,16 @@ var asyncNoHandleError1 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var listeners = [
|
var listeners = [
|
||||||
process.addAsyncListener(asyncNoHandleError0),
|
tracing.addAsyncListener(asyncNoHandleError0),
|
||||||
process.addAsyncListener(asyncNoHandleError1)
|
tracing.addAsyncListener(asyncNoHandleError1)
|
||||||
];
|
];
|
||||||
|
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
});
|
});
|
||||||
|
|
||||||
process.removeAsyncListener(listeners[0]);
|
tracing.removeAsyncListener(listeners[0]);
|
||||||
process.removeAsyncListener(listeners[1]);
|
tracing.removeAsyncListener(listeners[1]);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
// If the exit code isn't ok then return early to throw the stack that
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var results = [];
|
var results = [];
|
||||||
var asyncNoHandleError = {
|
var asyncNoHandleError = {
|
||||||
@ -37,8 +38,8 @@ var asyncHandleError = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var listeners = [
|
var listeners = [
|
||||||
process.addAsyncListener(asyncHandleError),
|
tracing.addAsyncListener(asyncHandleError),
|
||||||
process.addAsyncListener(asyncNoHandleError)
|
tracing.addAsyncListener(asyncNoHandleError)
|
||||||
];
|
];
|
||||||
|
|
||||||
// Even if an error handler returns true, both should fire.
|
// Even if an error handler returns true, both should fire.
|
||||||
@ -46,8 +47,8 @@ process.nextTick(function() {
|
|||||||
throw new Error();
|
throw new Error();
|
||||||
});
|
});
|
||||||
|
|
||||||
process.removeAsyncListener(listeners[0]);
|
tracing.removeAsyncListener(listeners[0]);
|
||||||
process.removeAsyncListener(listeners[1]);
|
tracing.removeAsyncListener(listeners[1]);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
// If the exit code isn't ok then return early to throw the stack that
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
function onAsync0() {
|
function onAsync0() {
|
||||||
return 0;
|
return 0;
|
||||||
@ -45,8 +46,8 @@ var asyncNoHandleError1 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var listeners = [
|
var listeners = [
|
||||||
process.addAsyncListener(asyncNoHandleError0),
|
tracing.addAsyncListener(asyncNoHandleError0),
|
||||||
process.addAsyncListener(asyncNoHandleError1)
|
tracing.addAsyncListener(asyncNoHandleError1)
|
||||||
];
|
];
|
||||||
|
|
||||||
var uncaughtFired = false;
|
var uncaughtFired = false;
|
||||||
@ -71,7 +72,7 @@ process.on('exit', function(code) {
|
|||||||
|
|
||||||
// Need to remove the async listeners or tests will always pass
|
// Need to remove the async listeners or tests will always pass
|
||||||
for (var i = 0; i < listeners.length; i++)
|
for (var i = 0; i < listeners.length; i++)
|
||||||
process.removeAsyncListener(listeners[i]);
|
tracing.removeAsyncListener(listeners[i]);
|
||||||
|
|
||||||
assert.ok(uncaughtFired);
|
assert.ok(uncaughtFired);
|
||||||
console.log('ok');
|
console.log('ok');
|
||||||
|
@ -24,6 +24,7 @@ var assert = require('assert');
|
|||||||
var dns = require('dns');
|
var dns = require('dns');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var net = require('net');
|
var net = require('net');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var errorMsgs = [];
|
var errorMsgs = [];
|
||||||
var caught = 0;
|
var caught = 0;
|
||||||
@ -45,10 +46,10 @@ var callbacksObj = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var listener = process.addAsyncListener(callbacksObj);
|
var listener = tracing.addAsyncListener(callbacksObj);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
process.removeAsyncListener(listener);
|
tracing.removeAsyncListener(listener);
|
||||||
|
|
||||||
if (code > 0)
|
if (code > 0)
|
||||||
return;
|
return;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var once = 0;
|
var once = 0;
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ var handlers = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = process.addAsyncListener(handlers);
|
var key = tracing.addAsyncListener(handlers);
|
||||||
|
|
||||||
var uncaughtFired = false;
|
var uncaughtFired = false;
|
||||||
process.on('uncaughtException', function(err) {
|
process.on('uncaughtException', function(err) {
|
||||||
@ -48,7 +49,7 @@ process.on('uncaughtException', function(err) {
|
|||||||
|
|
||||||
process.nextTick(function() { });
|
process.nextTick(function() { });
|
||||||
|
|
||||||
process.removeAsyncListener(key);
|
tracing.removeAsyncListener(key);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
// If the exit code isn't ok then return early to throw the stack that
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var once = 0;
|
var once = 0;
|
||||||
|
|
||||||
@ -50,8 +51,8 @@ var handlers1 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var listeners = [
|
var listeners = [
|
||||||
process.addAsyncListener(handlers),
|
tracing.addAsyncListener(handlers),
|
||||||
process.addAsyncListener(handlers1)
|
tracing.addAsyncListener(handlers1)
|
||||||
];
|
];
|
||||||
|
|
||||||
var uncaughtFired = false;
|
var uncaughtFired = false;
|
||||||
@ -65,7 +66,7 @@ process.on('uncaughtException', function(err) {
|
|||||||
process.nextTick(function() { });
|
process.nextTick(function() { });
|
||||||
|
|
||||||
for (var i = 0; i < listeners.length; i++)
|
for (var i = 0; i < listeners.length; i++)
|
||||||
process.removeAsyncListener(listeners[i]);
|
tracing.removeAsyncListener(listeners[i]);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
// If the exit code isn't ok then return early to throw the stack that
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var once = 0;
|
var once = 0;
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ var handlers = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = process.addAsyncListener(handlers);
|
var key = tracing.addAsyncListener(handlers);
|
||||||
|
|
||||||
var uncaughtFired = false;
|
var uncaughtFired = false;
|
||||||
process.on('uncaughtException', function(err) {
|
process.on('uncaughtException', function(err) {
|
||||||
@ -49,7 +50,7 @@ process.on('uncaughtException', function(err) {
|
|||||||
|
|
||||||
process.nextTick(function() { });
|
process.nextTick(function() { });
|
||||||
|
|
||||||
process.removeAsyncListener(key);
|
tracing.removeAsyncListener(key);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
// If the exit code isn't ok then return early to throw the stack that
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var spawn = require('child_process').spawn;
|
var spawn = require('child_process').spawn;
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var checkStr = 'WRITTEN ON EXIT';
|
var checkStr = 'WRITTEN ON EXIT';
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ else
|
|||||||
function runChild() {
|
function runChild() {
|
||||||
var cntr = 0;
|
var cntr = 0;
|
||||||
|
|
||||||
var key = process.addAsyncListener({
|
var key = tracing.addAsyncListener({
|
||||||
error: function onError() {
|
error: function onError() {
|
||||||
cntr++;
|
cntr++;
|
||||||
throw new Error('onError');
|
throw new Error('onError');
|
||||||
|
@ -24,9 +24,10 @@ var assert = require('assert');
|
|||||||
var dns = require('dns');
|
var dns = require('dns');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var net = require('net');
|
var net = require('net');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var addListener = process.addAsyncListener;
|
var addListener = tracing.addAsyncListener;
|
||||||
var removeListener = process.removeAsyncListener;
|
var removeListener = tracing.removeAsyncListener;
|
||||||
var errorMsgs = [];
|
var errorMsgs = [];
|
||||||
var currentMsg = '';
|
var currentMsg = '';
|
||||||
var caught = 0;
|
var caught = 0;
|
||||||
@ -46,7 +47,7 @@ var callbacksObj = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var listener = process.createAsyncListener(callbacksObj);
|
var listener = tracing.createAsyncListener(callbacksObj);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
removeListener(listener);
|
removeListener(listener);
|
||||||
|
@ -21,9 +21,10 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var addListener = process.addAsyncListener;
|
var addListener = tracing.addAsyncListener;
|
||||||
var removeListener = process.removeAsyncListener;
|
var removeListener = tracing.removeAsyncListener;
|
||||||
var caught = [];
|
var caught = [];
|
||||||
var expect = [];
|
var expect = [];
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ var callbacksObj = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var listener = process.createAsyncListener(callbacksObj);
|
var listener = tracing.createAsyncListener(callbacksObj);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
removeListener(listener);
|
removeListener(listener);
|
||||||
|
@ -21,26 +21,27 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
var val;
|
var val;
|
||||||
var callbacks = {
|
var callbacks = {
|
||||||
create: function() {
|
create: function() {
|
||||||
return 42;
|
return 42;
|
||||||
},
|
},
|
||||||
before: function() {
|
before: function() {
|
||||||
process.removeAsyncListener(listener);
|
tracing.removeAsyncListener(listener);
|
||||||
process.addAsyncListener(listener);
|
tracing.addAsyncListener(listener);
|
||||||
},
|
},
|
||||||
after: function(context, storage) {
|
after: function(context, storage) {
|
||||||
val = storage;
|
val = storage;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var listener = process.addAsyncListener(callbacks);
|
var listener = tracing.addAsyncListener(callbacks);
|
||||||
|
|
||||||
process.nextTick(function() {});
|
process.nextTick(function() {});
|
||||||
|
|
||||||
process.on('exit', function(status) {
|
process.on('exit', function(status) {
|
||||||
process.removeAsyncListener(listener);
|
tracing.removeAsyncListener(listener);
|
||||||
assert.equal(status, 0);
|
assert.equal(status, 0);
|
||||||
assert.equal(val, 42);
|
assert.equal(val, 42);
|
||||||
});
|
});
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
var set = 0;
|
var set = 0;
|
||||||
|
|
||||||
var asyncNoHandleError = {
|
var asyncNoHandleError = {
|
||||||
@ -32,9 +33,9 @@ var asyncNoHandleError = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = process.addAsyncListener(asyncNoHandleError);
|
var key = tracing.addAsyncListener(asyncNoHandleError);
|
||||||
|
|
||||||
process.removeAsyncListener(key);
|
tracing.removeAsyncListener(key);
|
||||||
|
|
||||||
process.nextTick(function() { });
|
process.nextTick(function() { });
|
||||||
|
|
||||||
|
@ -21,22 +21,23 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
var done = false;
|
var done = false;
|
||||||
var callbacks = {
|
var callbacks = {
|
||||||
before: function() {
|
before: function() {
|
||||||
process.removeAsyncListener(listener);
|
tracing.removeAsyncListener(listener);
|
||||||
},
|
},
|
||||||
after: function() {
|
after: function() {
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var listener = process.addAsyncListener(callbacks);
|
var listener = tracing.addAsyncListener(callbacks);
|
||||||
|
|
||||||
process.nextTick(function() {});
|
process.nextTick(function() {});
|
||||||
|
|
||||||
process.on('exit', function(status) {
|
process.on('exit', function(status) {
|
||||||
process.removeAsyncListener(listener);
|
tracing.removeAsyncListener(listener);
|
||||||
assert.equal(status, 0);
|
assert.equal(status, 0);
|
||||||
assert.ok(done);
|
assert.ok(done);
|
||||||
});
|
});
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var set = 0;
|
var set = 0;
|
||||||
var asyncNoHandleError = {
|
var asyncNoHandleError = {
|
||||||
@ -29,13 +30,13 @@ var asyncNoHandleError = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = process.addAsyncListener(asyncNoHandleError);
|
var key = tracing.addAsyncListener(asyncNoHandleError);
|
||||||
|
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
throw 1;
|
throw 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
process.removeAsyncListener(key);
|
tracing.removeAsyncListener(key);
|
||||||
|
|
||||||
var uncaughtFired = false;
|
var uncaughtFired = false;
|
||||||
process.on('uncaughtException', function() {
|
process.on('uncaughtException', function() {
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var set = 0;
|
var set = 0;
|
||||||
var asyncNoHandleError = {
|
var asyncNoHandleError = {
|
||||||
@ -32,11 +33,11 @@ var asyncNoHandleError = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = process.addAsyncListener(asyncNoHandleError);
|
var key = tracing.addAsyncListener(asyncNoHandleError);
|
||||||
|
|
||||||
process.nextTick(function() { });
|
process.nextTick(function() { });
|
||||||
|
|
||||||
process.removeAsyncListener(key);
|
tracing.removeAsyncListener(key);
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
process.on('exit', function(code) {
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
// If the exit code isn't ok then return early to throw the stack that
|
||||||
|
@ -22,9 +22,10 @@
|
|||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var net = require('net');
|
var net = require('net');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var cntr = 0;
|
var cntr = 0;
|
||||||
var al = process.addAsyncListener({
|
var al = tracing.addAsyncListener({
|
||||||
error: function(stor, er) {
|
error: function(stor, er) {
|
||||||
cntr++;
|
cntr++;
|
||||||
process._rawDebug('Handling error: ' + er.message);
|
process._rawDebug('Handling error: ' + er.message);
|
||||||
@ -33,7 +34,7 @@ var al = process.addAsyncListener({
|
|||||||
});
|
});
|
||||||
|
|
||||||
process.on('exit', function(status) {
|
process.on('exit', function(status) {
|
||||||
process.removeAsyncListener(al);
|
tracing.removeAsyncListener(al);
|
||||||
|
|
||||||
assert.equal(status, 0);
|
assert.equal(status, 0);
|
||||||
assert.equal(cntr, 1);
|
assert.equal(cntr, 1);
|
||||||
|
@ -21,9 +21,10 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var cntr = 0;
|
var cntr = 0;
|
||||||
var al = process.createAsyncListener({
|
var al = tracing.createAsyncListener({
|
||||||
create: function() { cntr++; },
|
create: function() { cntr++; },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -32,12 +33,12 @@ process.on('exit', function() {
|
|||||||
console.log('ok');
|
console.log('ok');
|
||||||
});
|
});
|
||||||
|
|
||||||
process.addAsyncListener(al);
|
tracing.addAsyncListener(al);
|
||||||
|
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
process.addAsyncListener(al);
|
tracing.addAsyncListener(al);
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
process.addAsyncListener(al);
|
tracing.addAsyncListener(al);
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
process.nextTick(function() { });
|
process.nextTick(function() { });
|
||||||
});
|
});
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
var common = require('../common');
|
var common = require('../common');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
// If there is an uncaughtException listener then the error thrown from
|
// If there is an uncaughtException listener then the error thrown from
|
||||||
// "before" will be considered handled, thus calling setImmediate to
|
// "before" will be considered handled, thus calling setImmediate to
|
||||||
@ -31,7 +32,7 @@ var assert = require('assert');
|
|||||||
var cntr = 0;
|
var cntr = 0;
|
||||||
|
|
||||||
|
|
||||||
process.addAsyncListener({
|
tracing.addAsyncListener({
|
||||||
before: function() {
|
before: function() {
|
||||||
if (++cntr > 1) {
|
if (++cntr > 1) {
|
||||||
// Can't throw since uncaughtException will also catch that.
|
// Can't throw since uncaughtException will also catch that.
|
||||||
|
@ -24,9 +24,10 @@ var assert = require('assert');
|
|||||||
var net = require('net');
|
var net = require('net');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var dgram = require('dgram');
|
var dgram = require('dgram');
|
||||||
|
var tracing = require('tracing');
|
||||||
|
|
||||||
var addListener = process.addAsyncListener;
|
var addListener = tracing.addAsyncListener;
|
||||||
var removeListener = process.removeAsyncListener;
|
var removeListener = tracing.removeAsyncListener;
|
||||||
var actualAsync = 0;
|
var actualAsync = 0;
|
||||||
var expectAsync = 0;
|
var expectAsync = 0;
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ var callbacks = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var listener = process.createAsyncListener(callbacks);
|
var listener = tracing.createAsyncListener(callbacks);
|
||||||
|
|
||||||
process.on('exit', function() {
|
process.on('exit', function() {
|
||||||
process._rawDebug('expected', expectAsync);
|
process._rawDebug('expected', expectAsync);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user