src: remove Async Listener
Async Listener was the name of the user-facing JS API, and is being completely removed. Instead low level hooks directly into the mechanism that AL used will be introduced in a future commit. PR-URL: https://github.com/joyent/node/pull/8110 Signed-off-by: Trevor Norris <trev.norris@gmail.com> Reviewed-by: Fedor Indutny <fedor@indutny.com> Reviewed-by: Alexis Campailla <alexis@janeasystems.com> Reviewed-by: Julien Gilli <julien.gilli@joyent.com>
This commit is contained in:
parent
4d94658918
commit
0d60ab3efe
@ -5,16 +5,6 @@
|
|||||||
The tracing module is designed for instrumenting your Node application. It is
|
The tracing module is designed for instrumenting your Node application. It is
|
||||||
not meant for general purpose use.
|
not meant for general purpose use.
|
||||||
|
|
||||||
***Be very careful with callbacks used in conjunction with this module***
|
|
||||||
|
|
||||||
Many of these callbacks interact directly with asynchronous subsystems in a
|
|
||||||
synchronous fashion. That is to say, you may be in a callback where a call to
|
|
||||||
`console.log()` could result in an infinite recursive loop. Also of note, many
|
|
||||||
of these callbacks are in hot execution code paths. That is to say your
|
|
||||||
callbacks are executed quite often in the normal operation of Node, so be wary
|
|
||||||
of doing CPU bound or synchronous workloads in these functions. Consider a ring
|
|
||||||
buffer and a timer to defer processing.
|
|
||||||
|
|
||||||
`require('tracing')` to use this module.
|
`require('tracing')` to use this module.
|
||||||
|
|
||||||
## v8
|
## v8
|
||||||
@ -73,216 +63,4 @@ v8.setFlagsFromString('--trace_gc');
|
|||||||
setTimeout(function() { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
|
setTimeout(function() { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# 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
|
|
||||||
[Timers]: timers.html
|
|
||||||
[`tracing.createAsyncListener()`]: #tracing_tracing_createasynclistener_asynclistener_callbacksobj_storagevalue
|
|
||||||
[`tracing.addAsyncListener()`]: #tracing_tracing_addasynclistener_asynclistener
|
|
||||||
[`tracing.removeAsyncListener()`]: #tracing_tracing_removeasynclistener_asynclistener
|
|
||||||
|
@ -32,21 +32,6 @@ var TIMEOUT_MAX = 2147483647; // 2^31-1
|
|||||||
|
|
||||||
var debug = require('util').debuglog('timer');
|
var debug = require('util').debuglog('timer');
|
||||||
|
|
||||||
var tracing = require('tracing');
|
|
||||||
var asyncFlags = tracing._asyncFlags;
|
|
||||||
var runAsyncQueue = tracing._runAsyncQueue;
|
|
||||||
var loadAsyncQueue = tracing._loadAsyncQueue;
|
|
||||||
var unloadAsyncQueue = tracing._unloadAsyncQueue;
|
|
||||||
|
|
||||||
// Same as in AsyncListener in env.h
|
|
||||||
var kHasListener = 0;
|
|
||||||
|
|
||||||
// Do a little housekeeping.
|
|
||||||
delete tracing._asyncFlags;
|
|
||||||
delete tracing._runAsyncQueue;
|
|
||||||
delete tracing._loadAsyncQueue;
|
|
||||||
delete tracing._unloadAsyncQueue;
|
|
||||||
|
|
||||||
|
|
||||||
// IDLE TIMEOUTS
|
// IDLE TIMEOUTS
|
||||||
//
|
//
|
||||||
@ -61,11 +46,6 @@ delete tracing._unloadAsyncQueue;
|
|||||||
// value = list
|
// value = list
|
||||||
var lists = {};
|
var lists = {};
|
||||||
|
|
||||||
// Make Timer as monomorphic as possible.
|
|
||||||
Timer.prototype._asyncQueue = undefined;
|
|
||||||
Timer.prototype._asyncData = undefined;
|
|
||||||
Timer.prototype._asyncFlags = 0;
|
|
||||||
|
|
||||||
// the main function - creates lists on demand and the watchers associated
|
// the main function - creates lists on demand and the watchers associated
|
||||||
// with them.
|
// with them.
|
||||||
function insert(item, msecs) {
|
function insert(item, msecs) {
|
||||||
@ -102,7 +82,7 @@ function listOnTimeout() {
|
|||||||
var now = Timer.now();
|
var now = Timer.now();
|
||||||
debug('now: %s', now);
|
debug('now: %s', now);
|
||||||
|
|
||||||
var diff, first, hasQueue, threw;
|
var diff, first, threw;
|
||||||
while (first = L.peek(list)) {
|
while (first = L.peek(list)) {
|
||||||
diff = now - first._idleStart;
|
diff = now - first._idleStart;
|
||||||
if (diff < msecs) {
|
if (diff < msecs) {
|
||||||
@ -124,19 +104,13 @@ function listOnTimeout() {
|
|||||||
if (domain && domain._disposed)
|
if (domain && domain._disposed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
hasQueue = !!first._asyncQueue;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (hasQueue)
|
|
||||||
loadAsyncQueue(first);
|
|
||||||
if (domain)
|
if (domain)
|
||||||
domain.enter();
|
domain.enter();
|
||||||
threw = true;
|
threw = true;
|
||||||
first._onTimeout();
|
first._onTimeout();
|
||||||
if (domain)
|
if (domain)
|
||||||
domain.exit();
|
domain.exit();
|
||||||
if (hasQueue)
|
|
||||||
unloadAsyncQueue(first);
|
|
||||||
threw = false;
|
threw = false;
|
||||||
} finally {
|
} finally {
|
||||||
if (threw) {
|
if (threw) {
|
||||||
@ -206,11 +180,6 @@ exports.active = function(item) {
|
|||||||
L.append(list, item);
|
L.append(list, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Whether or not a new TimerWrap needed to be created, this should run
|
|
||||||
// for each item. This way each "item" (i.e. timer) can properly have
|
|
||||||
// their own domain assigned.
|
|
||||||
if (asyncFlags[kHasListener] > 0)
|
|
||||||
runAsyncQueue(item);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -356,18 +325,15 @@ L.init(immediateQueue);
|
|||||||
|
|
||||||
function processImmediate() {
|
function processImmediate() {
|
||||||
var queue = immediateQueue;
|
var queue = immediateQueue;
|
||||||
var domain, hasQueue, immediate;
|
var domain, immediate;
|
||||||
|
|
||||||
immediateQueue = {};
|
immediateQueue = {};
|
||||||
L.init(immediateQueue);
|
L.init(immediateQueue);
|
||||||
|
|
||||||
while (L.isEmpty(queue) === false) {
|
while (L.isEmpty(queue) === false) {
|
||||||
immediate = L.shift(queue);
|
immediate = L.shift(queue);
|
||||||
hasQueue = !!immediate._asyncQueue;
|
|
||||||
domain = immediate.domain;
|
domain = immediate.domain;
|
||||||
|
|
||||||
if (hasQueue)
|
|
||||||
loadAsyncQueue(immediate);
|
|
||||||
if (domain)
|
if (domain)
|
||||||
domain.enter();
|
domain.enter();
|
||||||
|
|
||||||
@ -391,8 +357,6 @@ function processImmediate() {
|
|||||||
|
|
||||||
if (domain)
|
if (domain)
|
||||||
domain.exit();
|
domain.exit();
|
||||||
if (hasQueue)
|
|
||||||
unloadAsyncQueue(immediate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only round-trip to C++ land if we have to. Calling clearImmediate() on an
|
// Only round-trip to C++ land if we have to. Calling clearImmediate() on an
|
||||||
@ -408,11 +372,8 @@ function Immediate() { }
|
|||||||
|
|
||||||
Immediate.prototype.domain = undefined;
|
Immediate.prototype.domain = undefined;
|
||||||
Immediate.prototype._onImmediate = undefined;
|
Immediate.prototype._onImmediate = undefined;
|
||||||
Immediate.prototype._asyncQueue = undefined;
|
|
||||||
Immediate.prototype._asyncData = undefined;
|
|
||||||
Immediate.prototype._idleNext = undefined;
|
Immediate.prototype._idleNext = undefined;
|
||||||
Immediate.prototype._idlePrev = undefined;
|
Immediate.prototype._idlePrev = undefined;
|
||||||
Immediate.prototype._asyncFlags = 0;
|
|
||||||
|
|
||||||
|
|
||||||
exports.setImmediate = function(callback) {
|
exports.setImmediate = function(callback) {
|
||||||
@ -438,9 +399,6 @@ exports.setImmediate = function(callback) {
|
|||||||
process._immediateCallback = processImmediate;
|
process._immediateCallback = processImmediate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setImmediates are handled more like nextTicks.
|
|
||||||
if (asyncFlags[kHasListener] > 0)
|
|
||||||
runAsyncQueue(immediate);
|
|
||||||
if (process.domain)
|
if (process.domain)
|
||||||
immediate.domain = process.domain;
|
immediate.domain = process.domain;
|
||||||
|
|
||||||
@ -474,7 +432,7 @@ function unrefTimeout() {
|
|||||||
|
|
||||||
debug('unrefTimer fired');
|
debug('unrefTimer fired');
|
||||||
|
|
||||||
var diff, domain, first, hasQueue, threw;
|
var diff, domain, first, threw;
|
||||||
while (first = L.peek(unrefList)) {
|
while (first = L.peek(unrefList)) {
|
||||||
diff = now - first._idleStart;
|
diff = now - first._idleStart;
|
||||||
|
|
||||||
@ -492,11 +450,8 @@ function unrefTimeout() {
|
|||||||
|
|
||||||
if (!first._onTimeout) continue;
|
if (!first._onTimeout) continue;
|
||||||
if (domain && domain._disposed) continue;
|
if (domain && domain._disposed) continue;
|
||||||
hasQueue = !!first._asyncQueue;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (hasQueue)
|
|
||||||
loadAsyncQueue(first);
|
|
||||||
if (domain) domain.enter();
|
if (domain) domain.enter();
|
||||||
threw = true;
|
threw = true;
|
||||||
debug('unreftimer firing timeout');
|
debug('unreftimer firing timeout');
|
||||||
@ -504,8 +459,6 @@ function unrefTimeout() {
|
|||||||
threw = false;
|
threw = false;
|
||||||
if (domain)
|
if (domain)
|
||||||
domain.exit();
|
domain.exit();
|
||||||
if (hasQueue)
|
|
||||||
unloadAsyncQueue(first);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (threw) process.nextTick(unrefTimeout);
|
if (threw) process.nextTick(unrefTimeout);
|
||||||
}
|
}
|
||||||
|
333
lib/tracing.js
333
lib/tracing.js
@ -35,13 +35,6 @@ exports._nodeInitialization = function nodeInitialization(pobj) {
|
|||||||
v8.getHeapStatistics = v8binding.getHeapStatistics;
|
v8.getHeapStatistics = v8binding.getHeapStatistics;
|
||||||
v8.setFlagsFromString = v8binding.setFlagsFromString;
|
v8.setFlagsFromString = v8binding.setFlagsFromString;
|
||||||
|
|
||||||
// Part of the AsyncListener setup to share objects/callbacks with the
|
|
||||||
// native layer.
|
|
||||||
process._setupAsyncListener(asyncFlags,
|
|
||||||
runAsyncQueue,
|
|
||||||
loadAsyncQueue,
|
|
||||||
unloadAsyncQueue);
|
|
||||||
|
|
||||||
// Do a little housekeeping.
|
// Do a little housekeeping.
|
||||||
delete exports._nodeInitialization;
|
delete exports._nodeInitialization;
|
||||||
};
|
};
|
||||||
@ -70,329 +63,3 @@ v8.on('removeListener', function(name) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// 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, 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;
|
|
||||||
}
|
|
||||||
|
@ -37,20 +37,7 @@ inline AsyncWrap::AsyncWrap(Environment* env,
|
|||||||
v8::Handle<v8::Object> object,
|
v8::Handle<v8::Object> object,
|
||||||
ProviderType provider)
|
ProviderType provider)
|
||||||
: BaseObject(env, object),
|
: BaseObject(env, object),
|
||||||
async_flags_(NO_OPTIONS),
|
|
||||||
provider_type_(provider) {
|
provider_type_(provider) {
|
||||||
if (!env->has_async_listener())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// TODO(trevnorris): Do we really need to TryCatch this call?
|
|
||||||
v8::TryCatch try_catch;
|
|
||||||
try_catch.SetVerbose(true);
|
|
||||||
|
|
||||||
v8::Local<v8::Value> val = object.As<v8::Value>();
|
|
||||||
env->async_listener_run_function()->Call(env->process_object(), 1, &val);
|
|
||||||
|
|
||||||
if (!try_catch.HasCaught())
|
|
||||||
async_flags_ |= HAS_ASYNC_LISTENER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,11 +46,6 @@ inline uint32_t AsyncWrap::provider_type() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool AsyncWrap::has_async_listener() {
|
|
||||||
return async_flags_ & HAS_ASYNC_LISTENER;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// I hate you domains.
|
// I hate you domains.
|
||||||
inline v8::Handle<v8::Value> AsyncWrap::MakeDomainCallback(
|
inline v8::Handle<v8::Value> AsyncWrap::MakeDomainCallback(
|
||||||
const v8::Handle<v8::Function> cb,
|
const v8::Handle<v8::Function> cb,
|
||||||
@ -79,14 +61,6 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeDomainCallback(
|
|||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
|
|
||||||
if (has_async_listener()) {
|
|
||||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
|
||||||
env()->async_listener_load_function()->Call(process, 1, &val);
|
|
||||||
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return v8::Undefined(env()->isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_domain = domain_v->IsObject();
|
bool has_domain = domain_v->IsObject();
|
||||||
if (has_domain) {
|
if (has_domain) {
|
||||||
domain = domain_v.As<v8::Object>();
|
domain = domain_v.As<v8::Object>();
|
||||||
@ -119,14 +93,6 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeDomainCallback(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_async_listener()) {
|
|
||||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
|
||||||
env()->async_listener_unload_function()->Call(process, 1, &val);
|
|
||||||
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return Undefined(env()->isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment::TickInfo* tick_info = env()->tick_info();
|
Environment::TickInfo* tick_info = env()->tick_info();
|
||||||
|
|
||||||
if (tick_info->in_tick()) {
|
if (tick_info->in_tick()) {
|
||||||
@ -172,28 +138,12 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeCallback(
|
|||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
|
|
||||||
if (has_async_listener()) {
|
|
||||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
|
||||||
env()->async_listener_load_function()->Call(process, 1, &val);
|
|
||||||
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return v8::Undefined(env()->isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::Local<v8::Value> ret = cb->Call(context, argc, argv);
|
v8::Local<v8::Value> ret = cb->Call(context, argc, argv);
|
||||||
|
|
||||||
if (try_catch.HasCaught()) {
|
if (try_catch.HasCaught()) {
|
||||||
return Undefined(env()->isolate());
|
return Undefined(env()->isolate());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_async_listener()) {
|
|
||||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
|
||||||
env()->async_listener_unload_function()->Call(process, 1, &val);
|
|
||||||
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return v8::Undefined(env()->isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment::TickInfo* tick_info = env()->tick_info();
|
Environment::TickInfo* tick_info = env()->tick_info();
|
||||||
|
|
||||||
if (tick_info->in_tick()) {
|
if (tick_info->in_tick()) {
|
||||||
|
@ -30,11 +30,6 @@ namespace node {
|
|||||||
|
|
||||||
class AsyncWrap : public BaseObject {
|
class AsyncWrap : public BaseObject {
|
||||||
public:
|
public:
|
||||||
enum AsyncFlags {
|
|
||||||
NO_OPTIONS = 0,
|
|
||||||
HAS_ASYNC_LISTENER = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ProviderType {
|
enum ProviderType {
|
||||||
PROVIDER_NONE = 1 << 0,
|
PROVIDER_NONE = 1 << 0,
|
||||||
PROVIDER_CARES = 1 << 1,
|
PROVIDER_CARES = 1 << 1,
|
||||||
@ -63,8 +58,6 @@ class AsyncWrap : public BaseObject {
|
|||||||
|
|
||||||
inline virtual ~AsyncWrap() override = default;
|
inline virtual ~AsyncWrap() override = default;
|
||||||
|
|
||||||
inline bool has_async_listener();
|
|
||||||
|
|
||||||
inline uint32_t provider_type() const;
|
inline uint32_t provider_type() const;
|
||||||
|
|
||||||
// Only call these within a valid HandleScope.
|
// Only call these within a valid HandleScope.
|
||||||
@ -88,7 +81,6 @@ class AsyncWrap : public BaseObject {
|
|||||||
int argc,
|
int argc,
|
||||||
v8::Handle<v8::Value>* argv);
|
v8::Handle<v8::Value>* argv);
|
||||||
|
|
||||||
uint32_t async_flags_;
|
|
||||||
uint32_t provider_type_;
|
uint32_t provider_type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,27 +111,6 @@ inline v8::Isolate* Environment::IsolateData::isolate() const {
|
|||||||
return isolate_;
|
return isolate_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Environment::AsyncListener::AsyncListener() {
|
|
||||||
for (int i = 0; i < kFieldsCount; ++i)
|
|
||||||
fields_[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t* Environment::AsyncListener::fields() {
|
|
||||||
return fields_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int Environment::AsyncListener::fields_count() const {
|
|
||||||
return kFieldsCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Environment::AsyncListener::has_listener() const {
|
|
||||||
return fields_[kHasListener] > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t Environment::AsyncListener::watched_providers() const {
|
|
||||||
return fields_[kWatchedProviders];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Environment::DomainFlag::DomainFlag() {
|
inline Environment::DomainFlag::DomainFlag() {
|
||||||
for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
|
for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
|
||||||
}
|
}
|
||||||
@ -277,16 +256,6 @@ inline v8::Isolate* Environment::isolate() const {
|
|||||||
return isolate_;
|
return isolate_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Environment::has_async_listener() const {
|
|
||||||
// The const_cast is okay, it doesn't violate conceptual const-ness.
|
|
||||||
return const_cast<Environment*>(this)->async_listener()->has_listener();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t Environment::watched_providers() const {
|
|
||||||
// The const_cast is okay, it doesn't violate conceptual const-ness.
|
|
||||||
return const_cast<Environment*>(this)->async_listener()->watched_providers();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Environment::in_domain() const {
|
inline bool Environment::in_domain() const {
|
||||||
// The const_cast is okay, it doesn't violate conceptual const-ness.
|
// The const_cast is okay, it doesn't violate conceptual const-ness.
|
||||||
return using_domains() &&
|
return using_domains() &&
|
||||||
@ -338,10 +307,6 @@ inline uv_loop_t* Environment::event_loop() const {
|
|||||||
return isolate_data()->event_loop();
|
return isolate_data()->event_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Environment::AsyncListener* Environment::async_listener() {
|
|
||||||
return &async_listener_count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Environment::DomainFlag* Environment::domain_flag() {
|
inline Environment::DomainFlag* Environment::domain_flag() {
|
||||||
return &domain_flag_;
|
return &domain_flag_;
|
||||||
}
|
}
|
||||||
|
29
src/env.h
29
src/env.h
@ -64,7 +64,6 @@ namespace node {
|
|||||||
V(address_string, "address") \
|
V(address_string, "address") \
|
||||||
V(args_string, "args") \
|
V(args_string, "args") \
|
||||||
V(argv_string, "argv") \
|
V(argv_string, "argv") \
|
||||||
V(async_queue_string, "_asyncQueue") \
|
|
||||||
V(async, "async") \
|
V(async, "async") \
|
||||||
V(atime_string, "atime") \
|
V(atime_string, "atime") \
|
||||||
V(birthtime_string, "birthtime") \
|
V(birthtime_string, "birthtime") \
|
||||||
@ -250,9 +249,6 @@ namespace node {
|
|||||||
V(zero_return_string, "ZERO_RETURN") \
|
V(zero_return_string, "ZERO_RETURN") \
|
||||||
|
|
||||||
#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \
|
#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \
|
||||||
V(async_listener_run_function, v8::Function) \
|
|
||||||
V(async_listener_load_function, v8::Function) \
|
|
||||||
V(async_listener_unload_function, v8::Function) \
|
|
||||||
V(binding_cache_object, v8::Object) \
|
V(binding_cache_object, v8::Object) \
|
||||||
V(buffer_constructor_function, v8::Function) \
|
V(buffer_constructor_function, v8::Function) \
|
||||||
V(context, v8::Context) \
|
V(context, v8::Context) \
|
||||||
@ -286,28 +282,6 @@ RB_HEAD(ares_task_list, ares_task_t);
|
|||||||
|
|
||||||
class Environment {
|
class Environment {
|
||||||
public:
|
public:
|
||||||
class AsyncListener {
|
|
||||||
public:
|
|
||||||
inline uint32_t* fields();
|
|
||||||
inline int fields_count() const;
|
|
||||||
inline bool has_listener() const;
|
|
||||||
inline uint32_t watched_providers() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class Environment; // So we can call the constructor.
|
|
||||||
inline AsyncListener();
|
|
||||||
|
|
||||||
enum Fields {
|
|
||||||
kHasListener,
|
|
||||||
kWatchedProviders,
|
|
||||||
kFieldsCount
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t fields_[kFieldsCount];
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(AsyncListener);
|
|
||||||
};
|
|
||||||
|
|
||||||
class DomainFlag {
|
class DomainFlag {
|
||||||
public:
|
public:
|
||||||
inline uint32_t* fields();
|
inline uint32_t* fields();
|
||||||
@ -399,7 +373,6 @@ class Environment {
|
|||||||
|
|
||||||
inline v8::Isolate* isolate() const;
|
inline v8::Isolate* isolate() const;
|
||||||
inline uv_loop_t* event_loop() const;
|
inline uv_loop_t* event_loop() const;
|
||||||
inline bool has_async_listener() const;
|
|
||||||
inline bool in_domain() const;
|
inline bool in_domain() const;
|
||||||
inline uint32_t watched_providers() const;
|
inline uint32_t watched_providers() const;
|
||||||
|
|
||||||
@ -419,7 +392,6 @@ class Environment {
|
|||||||
void *arg);
|
void *arg);
|
||||||
inline void FinishHandleCleanup(uv_handle_t* handle);
|
inline void FinishHandleCleanup(uv_handle_t* handle);
|
||||||
|
|
||||||
inline AsyncListener* async_listener();
|
|
||||||
inline DomainFlag* domain_flag();
|
inline DomainFlag* domain_flag();
|
||||||
inline TickInfo* tick_info();
|
inline TickInfo* tick_info();
|
||||||
|
|
||||||
@ -513,7 +485,6 @@ class Environment {
|
|||||||
uv_idle_t immediate_idle_handle_;
|
uv_idle_t immediate_idle_handle_;
|
||||||
uv_prepare_t idle_prepare_handle_;
|
uv_prepare_t idle_prepare_handle_;
|
||||||
uv_check_t idle_check_handle_;
|
uv_check_t idle_check_handle_;
|
||||||
AsyncListener async_listener_count_;
|
|
||||||
DomainFlag domain_flag_;
|
DomainFlag domain_flag_;
|
||||||
TickInfo tick_info_;
|
TickInfo tick_info_;
|
||||||
uv_timer_t cares_timer_handle_;
|
uv_timer_t cares_timer_handle_;
|
||||||
|
63
src/node.cc
63
src/node.cc
@ -918,31 +918,6 @@ Local<Value> WinapiErrnoException(Isolate* isolate,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void SetupAsyncListener(const FunctionCallbackInfo<Value>& args) {
|
|
||||||
Environment* env = Environment::GetCurrent(args);
|
|
||||||
|
|
||||||
CHECK(args[0]->IsObject());
|
|
||||||
CHECK(args[1]->IsFunction());
|
|
||||||
CHECK(args[2]->IsFunction());
|
|
||||||
CHECK(args[3]->IsFunction());
|
|
||||||
|
|
||||||
env->set_async_listener_run_function(args[1].As<Function>());
|
|
||||||
env->set_async_listener_load_function(args[2].As<Function>());
|
|
||||||
env->set_async_listener_unload_function(args[3].As<Function>());
|
|
||||||
|
|
||||||
Local<Object> async_listener_flag_obj = args[0].As<Object>();
|
|
||||||
Environment::AsyncListener* async_listener = env->async_listener();
|
|
||||||
async_listener_flag_obj->SetIndexedPropertiesToExternalArrayData(
|
|
||||||
async_listener->fields(),
|
|
||||||
kExternalUint32Array,
|
|
||||||
async_listener->fields_count());
|
|
||||||
|
|
||||||
// Do a little housekeeping.
|
|
||||||
env->process_object()->Delete(
|
|
||||||
FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupAsyncListener"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
|
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
|
||||||
@ -1026,20 +1001,6 @@ Handle<Value> MakeDomainCallback(Environment* env,
|
|||||||
TryCatch try_catch;
|
TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
|
|
||||||
bool has_async_queue = false;
|
|
||||||
|
|
||||||
if (recv->IsObject()) {
|
|
||||||
object = recv.As<Object>();
|
|
||||||
// TODO(trevnorris): This is sucky for performance. Fix it.
|
|
||||||
has_async_queue = object->Has(env->async_queue_string());
|
|
||||||
if (has_async_queue) {
|
|
||||||
env->async_listener_load_function()->Call(process, 1, &recv);
|
|
||||||
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return Undefined(env->isolate());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_domain = false;
|
bool has_domain = false;
|
||||||
|
|
||||||
if (!object.IsEmpty()) {
|
if (!object.IsEmpty()) {
|
||||||
@ -1077,13 +1038,6 @@ Handle<Value> MakeDomainCallback(Environment* env,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_async_queue) {
|
|
||||||
env->async_listener_unload_function()->Call(process, 1, &recv);
|
|
||||||
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return Undefined(env->isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment::TickInfo* tick_info = env->tick_info();
|
Environment::TickInfo* tick_info = env->tick_info();
|
||||||
|
|
||||||
if (tick_info->last_threw() == 1) {
|
if (tick_info->last_threw() == 1) {
|
||||||
@ -1135,28 +1089,12 @@ Handle<Value> MakeCallback(Environment* env,
|
|||||||
TryCatch try_catch;
|
TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
|
|
||||||
// TODO(trevnorris): This is sucky for performance. Fix it.
|
|
||||||
bool has_async_queue =
|
|
||||||
recv->IsObject() && recv.As<Object>()->Has(env->async_queue_string());
|
|
||||||
if (has_async_queue) {
|
|
||||||
env->async_listener_load_function()->Call(process, 1, &recv);
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return Undefined(env->isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
Local<Value> ret = callback->Call(recv, argc, argv);
|
Local<Value> ret = callback->Call(recv, argc, argv);
|
||||||
|
|
||||||
if (try_catch.HasCaught()) {
|
if (try_catch.HasCaught()) {
|
||||||
return Undefined(env->isolate());
|
return Undefined(env->isolate());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_async_queue) {
|
|
||||||
env->async_listener_unload_function()->Call(process, 1, &recv);
|
|
||||||
|
|
||||||
if (try_catch.HasCaught())
|
|
||||||
return Undefined(env->isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment::TickInfo* tick_info = env->tick_info();
|
Environment::TickInfo* tick_info = env->tick_info();
|
||||||
|
|
||||||
if (tick_info->in_tick()) {
|
if (tick_info->in_tick()) {
|
||||||
@ -2865,7 +2803,6 @@ void SetupProcessObject(Environment* env,
|
|||||||
env->SetMethod(process, "binding", Binding);
|
env->SetMethod(process, "binding", Binding);
|
||||||
env->SetMethod(process, "_linkedBinding", LinkedBinding);
|
env->SetMethod(process, "_linkedBinding", LinkedBinding);
|
||||||
|
|
||||||
env->SetMethod(process, "_setupAsyncListener", SetupAsyncListener);
|
|
||||||
env->SetMethod(process, "_setupNextTick", SetupNextTick);
|
env->SetMethod(process, "_setupNextTick", SetupNextTick);
|
||||||
env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
|
env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
|
||||||
|
|
||||||
|
41
src/node.js
41
src/node.js
@ -232,14 +232,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
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.
|
var caught;
|
||||||
var caught = _errorHandler(er);
|
|
||||||
|
|
||||||
if (process.domain && process.domain._errorHandler)
|
if (process.domain && process.domain._errorHandler)
|
||||||
caught = process.domain._errorHandler(er) || caught;
|
caught = process.domain._errorHandler(er) || caught;
|
||||||
@ -262,10 +256,6 @@
|
|||||||
// if we handled an error, then make sure any ticks get processed
|
// if we handled an error, then make sure any ticks get processed
|
||||||
} else {
|
} else {
|
||||||
var t = setImmediate(process._tickCallback);
|
var t = setImmediate(process._tickCallback);
|
||||||
// Complete hack to make sure any errors thrown from async
|
|
||||||
// listeners don't cause an infinite loop.
|
|
||||||
if (t._asyncQueue)
|
|
||||||
t._asyncQueue = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return caught;
|
return caught;
|
||||||
@ -299,12 +289,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
startup.processNextTick = function() {
|
startup.processNextTick = function() {
|
||||||
var tracing = NativeModule.require('tracing');
|
|
||||||
var nextTickQueue = [];
|
var nextTickQueue = [];
|
||||||
var asyncFlags = tracing._asyncFlags;
|
|
||||||
var _runAsyncQueue = tracing._runAsyncQueue;
|
|
||||||
var _loadAsyncQueue = tracing._loadAsyncQueue;
|
|
||||||
var _unloadAsyncQueue = tracing._unloadAsyncQueue;
|
|
||||||
var microtasksScheduled = false;
|
var microtasksScheduled = false;
|
||||||
|
|
||||||
// Used to run V8's micro task queue.
|
// Used to run V8's micro task queue.
|
||||||
@ -318,10 +303,6 @@
|
|||||||
var kIndex = 0;
|
var kIndex = 0;
|
||||||
var kLength = 1;
|
var kLength = 1;
|
||||||
|
|
||||||
// For asyncFlags.
|
|
||||||
// *Must* match Environment::AsyncListeners::Fields in src/env.h
|
|
||||||
var kCount = 0;
|
|
||||||
|
|
||||||
process.nextTick = nextTick;
|
process.nextTick = nextTick;
|
||||||
// Needs to be accessible from beyond this scope.
|
// Needs to be accessible from beyond this scope.
|
||||||
process._tickCallback = _tickCallback;
|
process._tickCallback = _tickCallback;
|
||||||
@ -368,7 +349,7 @@
|
|||||||
// Run callbacks that have no domain.
|
// Run callbacks that have no domain.
|
||||||
// Using domains will cause this to be overridden.
|
// Using domains will cause this to be overridden.
|
||||||
function _tickCallback() {
|
function _tickCallback() {
|
||||||
var callback, hasQueue, threw, tock;
|
var callback, threw, tock;
|
||||||
|
|
||||||
scheduleMicrotasks();
|
scheduleMicrotasks();
|
||||||
|
|
||||||
@ -376,9 +357,6 @@
|
|||||||
tock = nextTickQueue[tickInfo[kIndex]++];
|
tock = nextTickQueue[tickInfo[kIndex]++];
|
||||||
callback = tock.callback;
|
callback = tock.callback;
|
||||||
threw = true;
|
threw = true;
|
||||||
hasQueue = !!tock._asyncQueue;
|
|
||||||
if (hasQueue)
|
|
||||||
_loadAsyncQueue(tock);
|
|
||||||
try {
|
try {
|
||||||
callback();
|
callback();
|
||||||
threw = false;
|
threw = false;
|
||||||
@ -386,8 +364,6 @@
|
|||||||
if (threw)
|
if (threw)
|
||||||
tickDone();
|
tickDone();
|
||||||
}
|
}
|
||||||
if (hasQueue)
|
|
||||||
_unloadAsyncQueue(tock);
|
|
||||||
if (1e4 < tickInfo[kIndex])
|
if (1e4 < tickInfo[kIndex])
|
||||||
tickDone();
|
tickDone();
|
||||||
}
|
}
|
||||||
@ -396,7 +372,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _tickDomainCallback() {
|
function _tickDomainCallback() {
|
||||||
var callback, domain, hasQueue, threw, tock;
|
var callback, domain, threw, tock;
|
||||||
|
|
||||||
scheduleMicrotasks();
|
scheduleMicrotasks();
|
||||||
|
|
||||||
@ -404,9 +380,6 @@
|
|||||||
tock = nextTickQueue[tickInfo[kIndex]++];
|
tock = nextTickQueue[tickInfo[kIndex]++];
|
||||||
callback = tock.callback;
|
callback = tock.callback;
|
||||||
domain = tock.domain;
|
domain = tock.domain;
|
||||||
hasQueue = !!tock._asyncQueue;
|
|
||||||
if (hasQueue)
|
|
||||||
_loadAsyncQueue(tock);
|
|
||||||
if (domain)
|
if (domain)
|
||||||
domain.enter();
|
domain.enter();
|
||||||
threw = true;
|
threw = true;
|
||||||
@ -417,8 +390,6 @@
|
|||||||
if (threw)
|
if (threw)
|
||||||
tickDone();
|
tickDone();
|
||||||
}
|
}
|
||||||
if (hasQueue)
|
|
||||||
_unloadAsyncQueue(tock);
|
|
||||||
if (1e4 < tickInfo[kIndex])
|
if (1e4 < tickInfo[kIndex])
|
||||||
tickDone();
|
tickDone();
|
||||||
if (domain)
|
if (domain)
|
||||||
@ -435,13 +406,9 @@
|
|||||||
|
|
||||||
var obj = {
|
var obj = {
|
||||||
callback: callback,
|
callback: callback,
|
||||||
domain: process.domain || null,
|
domain: process.domain || null
|
||||||
_asyncQueue: undefined
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (asyncFlags[kCount] > 0)
|
|
||||||
_runAsyncQueue(obj);
|
|
||||||
|
|
||||||
nextTickQueue.push(obj);
|
nextTickQueue.push(obj);
|
||||||
tickInfo[kLength]++;
|
tickInfo[kLength]++;
|
||||||
}
|
}
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var active = null;
|
|
||||||
var cntr = 0;
|
|
||||||
|
|
||||||
function onAsync0() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAsync1() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onError(stor) {
|
|
||||||
results.push(stor);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var results = [];
|
|
||||||
var asyncNoHandleError0 = {
|
|
||||||
create: onAsync0,
|
|
||||||
error: onError
|
|
||||||
};
|
|
||||||
var asyncNoHandleError1 = {
|
|
||||||
create: onAsync1,
|
|
||||||
error: onError
|
|
||||||
};
|
|
||||||
|
|
||||||
var listeners = [
|
|
||||||
tracing.addAsyncListener(asyncNoHandleError0),
|
|
||||||
tracing.addAsyncListener(asyncNoHandleError1)
|
|
||||||
];
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
throw new Error();
|
|
||||||
});
|
|
||||||
|
|
||||||
tracing.removeAsyncListener(listeners[0]);
|
|
||||||
tracing.removeAsyncListener(listeners[1]);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Handling of errors should propagate to all listeners.
|
|
||||||
assert.equal(results[0], 0);
|
|
||||||
assert.equal(results[1], 1);
|
|
||||||
assert.equal(results.length, 2);
|
|
||||||
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
@ -1,65 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var results = [];
|
|
||||||
var asyncNoHandleError = {
|
|
||||||
error: function(stor) {
|
|
||||||
results.push(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var asyncHandleError = {
|
|
||||||
error: function(stor) {
|
|
||||||
results.push(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var listeners = [
|
|
||||||
tracing.addAsyncListener(asyncHandleError),
|
|
||||||
tracing.addAsyncListener(asyncNoHandleError)
|
|
||||||
];
|
|
||||||
|
|
||||||
// Even if an error handler returns true, both should fire.
|
|
||||||
process.nextTick(function() {
|
|
||||||
throw new Error();
|
|
||||||
});
|
|
||||||
|
|
||||||
tracing.removeAsyncListener(listeners[0]);
|
|
||||||
tracing.removeAsyncListener(listeners[1]);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Mixed handling of errors should propagate to all listeners.
|
|
||||||
assert.equal(results[0], 0);
|
|
||||||
assert.equal(results[1], 1);
|
|
||||||
assert.equal(results.length, 2);
|
|
||||||
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
@ -1,79 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
function onAsync0() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAsync1() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onError(stor) {
|
|
||||||
results.push(stor);
|
|
||||||
}
|
|
||||||
|
|
||||||
var results = [];
|
|
||||||
var asyncNoHandleError0 = {
|
|
||||||
create: onAsync0,
|
|
||||||
error: onError
|
|
||||||
};
|
|
||||||
var asyncNoHandleError1 = {
|
|
||||||
create: onAsync1,
|
|
||||||
error: onError
|
|
||||||
};
|
|
||||||
|
|
||||||
var listeners = [
|
|
||||||
tracing.addAsyncListener(asyncNoHandleError0),
|
|
||||||
tracing.addAsyncListener(asyncNoHandleError1)
|
|
||||||
];
|
|
||||||
|
|
||||||
var uncaughtFired = false;
|
|
||||||
process.on('uncaughtException', function() {
|
|
||||||
uncaughtFired = true;
|
|
||||||
|
|
||||||
// Unhandled errors should propagate to all listeners.
|
|
||||||
assert.equal(results[0], 0);
|
|
||||||
assert.equal(results[1], 1);
|
|
||||||
assert.equal(results.length, 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
throw new Error();
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Need to remove the async listeners or tests will always pass
|
|
||||||
for (var i = 0; i < listeners.length; i++)
|
|
||||||
tracing.removeAsyncListener(listeners[i]);
|
|
||||||
|
|
||||||
assert.ok(uncaughtFired);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
@ -1,108 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var dns = require('dns');
|
|
||||||
var fs = require('fs');
|
|
||||||
var net = require('net');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var errorMsgs = [];
|
|
||||||
var caught = 0;
|
|
||||||
var expectCaught = 0;
|
|
||||||
|
|
||||||
var callbacksObj = {
|
|
||||||
error: function(value, er) {
|
|
||||||
var idx = errorMsgs.indexOf(er.message);
|
|
||||||
caught++;
|
|
||||||
|
|
||||||
process._rawDebug('Handling error: ' + er.message);
|
|
||||||
|
|
||||||
if (-1 < idx)
|
|
||||||
errorMsgs.splice(idx, 1);
|
|
||||||
else
|
|
||||||
throw new Error('Message not found: ' + er.message);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var listener = tracing.addAsyncListener(callbacksObj);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
tracing.removeAsyncListener(listener);
|
|
||||||
|
|
||||||
if (code > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (errorMsgs.length > 0)
|
|
||||||
throw new Error('Errors not fired: ' + errorMsgs);
|
|
||||||
|
|
||||||
assert.equal(caught, expectCaught);
|
|
||||||
process._rawDebug('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Net
|
|
||||||
var iter = 3;
|
|
||||||
for (var i = 0; i < iter; i++) {
|
|
||||||
errorMsgs.push('net - error: server connection');
|
|
||||||
errorMsgs.push('net - error: client data');
|
|
||||||
errorMsgs.push('net - error: server data');
|
|
||||||
}
|
|
||||||
errorMsgs.push('net - error: server closed');
|
|
||||||
|
|
||||||
var server = net.createServer(function(c) {
|
|
||||||
c.on('data', function() {
|
|
||||||
if (0 === --iter) {
|
|
||||||
server.close(function() {
|
|
||||||
process._rawDebug('net - server closing');
|
|
||||||
throw new Error('net - error: server closed');
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
}
|
|
||||||
process._rawDebug('net - connection received data');
|
|
||||||
throw new Error('net - error: server data');
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
c.end('bye');
|
|
||||||
process._rawDebug('net - connection received');
|
|
||||||
throw new Error('net - error: server connection');
|
|
||||||
});
|
|
||||||
expectCaught += iter;
|
|
||||||
|
|
||||||
server.listen(common.PORT, function() {
|
|
||||||
for (var i = 0; i < iter; i++)
|
|
||||||
clientConnect();
|
|
||||||
});
|
|
||||||
|
|
||||||
function clientConnect() {
|
|
||||||
var client = net.connect(common.PORT, function() { });
|
|
||||||
|
|
||||||
client.on('data', function() {
|
|
||||||
client.end('see ya');
|
|
||||||
process._rawDebug('net - client received data');
|
|
||||||
throw new Error('net - error: client data');
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var once = 0;
|
|
||||||
|
|
||||||
var results = [];
|
|
||||||
var handlers = {
|
|
||||||
after: function() {
|
|
||||||
throw 1;
|
|
||||||
},
|
|
||||||
error: function(stor, err) {
|
|
||||||
// Error handler must be called exactly *once*.
|
|
||||||
once++;
|
|
||||||
assert.equal(err, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var key = tracing.addAsyncListener(handlers);
|
|
||||||
|
|
||||||
var uncaughtFired = false;
|
|
||||||
process.on('uncaughtException', function(err) {
|
|
||||||
uncaughtFired = true;
|
|
||||||
|
|
||||||
assert.equal(once, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
|
|
||||||
tracing.removeAsyncListener(key);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
assert.ok(uncaughtFired);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
@ -1,80 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var once = 0;
|
|
||||||
|
|
||||||
var results = [];
|
|
||||||
var handlers = {
|
|
||||||
before: function() {
|
|
||||||
throw 1;
|
|
||||||
},
|
|
||||||
error: function(stor, err) {
|
|
||||||
// Must catch error thrown in before callback.
|
|
||||||
assert.equal(err, 1);
|
|
||||||
once++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var handlers1 = {
|
|
||||||
before: function() {
|
|
||||||
throw 2;
|
|
||||||
},
|
|
||||||
error: function(stor, err) {
|
|
||||||
// Must catch *other* handlers throw by error callback.
|
|
||||||
assert.equal(err, 1);
|
|
||||||
once++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var listeners = [
|
|
||||||
tracing.addAsyncListener(handlers),
|
|
||||||
tracing.addAsyncListener(handlers1)
|
|
||||||
];
|
|
||||||
|
|
||||||
var uncaughtFired = false;
|
|
||||||
process.on('uncaughtException', function(err) {
|
|
||||||
uncaughtFired = true;
|
|
||||||
|
|
||||||
// Both error handlers must fire.
|
|
||||||
assert.equal(once, 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
|
|
||||||
for (var i = 0; i < listeners.length; i++)
|
|
||||||
tracing.removeAsyncListener(listeners[i]);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
// Make sure uncaughtException actually fired.
|
|
||||||
assert.ok(uncaughtFired);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var once = 0;
|
|
||||||
|
|
||||||
var results = [];
|
|
||||||
var handlers = {
|
|
||||||
before: function() {
|
|
||||||
throw 1;
|
|
||||||
},
|
|
||||||
error: function(stor, err) {
|
|
||||||
// Error handler must be called exactly *once*.
|
|
||||||
once++;
|
|
||||||
assert.equal(err, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var key = tracing.addAsyncListener(handlers);
|
|
||||||
|
|
||||||
var uncaughtFired = false;
|
|
||||||
process.on('uncaughtException', function(err) {
|
|
||||||
uncaughtFired = true;
|
|
||||||
|
|
||||||
// Process should propagate error regardless of handlers return value.
|
|
||||||
assert.equal(once, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
|
|
||||||
tracing.removeAsyncListener(key);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Make sure that the uncaughtException actually fired.
|
|
||||||
assert.ok(uncaughtFired);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
@ -1,87 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var spawn = require('child_process').spawn;
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var checkStr = 'WRITTEN ON EXIT';
|
|
||||||
|
|
||||||
if (process.argv[2] === 'child')
|
|
||||||
runChild();
|
|
||||||
else
|
|
||||||
runParent();
|
|
||||||
|
|
||||||
|
|
||||||
function runChild() {
|
|
||||||
var cntr = 0;
|
|
||||||
|
|
||||||
var key = tracing.addAsyncListener({
|
|
||||||
error: function onError() {
|
|
||||||
cntr++;
|
|
||||||
throw new Error('onError');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('unhandledException', function() {
|
|
||||||
// Throwing in 'error' should bypass unhandledException.
|
|
||||||
process.exit(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', function() {
|
|
||||||
// Make sure that we can still write out to stderr even when the
|
|
||||||
// process dies.
|
|
||||||
process._rawDebug(checkStr);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
throw new Error('nextTick');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function runParent() {
|
|
||||||
var childDidExit = false;
|
|
||||||
var childStr = '';
|
|
||||||
var child = spawn(process.execPath, [__filename, 'child']);
|
|
||||||
child.stderr.on('data', function(chunk) {
|
|
||||||
process._rawDebug('received data from child');
|
|
||||||
childStr += chunk.toString();
|
|
||||||
});
|
|
||||||
|
|
||||||
child.on('exit', function(code) {
|
|
||||||
process._rawDebug('child process exiting');
|
|
||||||
childDidExit = true;
|
|
||||||
// This is thrown when Node throws from _fatalException.
|
|
||||||
assert.equal(code, 7);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', function() {
|
|
||||||
process._rawDebug('child ondata message:',
|
|
||||||
childStr.substr(0, checkStr.length));
|
|
||||||
|
|
||||||
assert.ok(childDidExit);
|
|
||||||
assert.equal(childStr.substr(0, checkStr.length), checkStr);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,257 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var dns = require('dns');
|
|
||||||
var fs = require('fs');
|
|
||||||
var net = require('net');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var addListener = tracing.addAsyncListener;
|
|
||||||
var removeListener = tracing.removeAsyncListener;
|
|
||||||
var errorMsgs = [];
|
|
||||||
var currentMsg = '';
|
|
||||||
var caught = 0;
|
|
||||||
var expectCaught = 0;
|
|
||||||
var exitCbRan = false;
|
|
||||||
|
|
||||||
var callbacksObj = {
|
|
||||||
error: function(value, er) {
|
|
||||||
var idx = errorMsgs.indexOf(er.message);
|
|
||||||
|
|
||||||
caught++;
|
|
||||||
|
|
||||||
if (-1 < idx)
|
|
||||||
errorMsgs.splice(idx, 1);
|
|
||||||
|
|
||||||
return currentMsg === er.message;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var listener = tracing.createAsyncListener(callbacksObj);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
removeListener(listener);
|
|
||||||
|
|
||||||
// Something else went wrong, no need to further check.
|
|
||||||
if (code > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Make sure the exit callback only runs once.
|
|
||||||
assert.ok(!exitCbRan);
|
|
||||||
exitCbRan = true;
|
|
||||||
|
|
||||||
// Check if any error messages weren't removed from the msg queue.
|
|
||||||
if (errorMsgs.length > 0)
|
|
||||||
throw new Error('Errors not fired: ' + errorMsgs);
|
|
||||||
|
|
||||||
assert.equal(caught, expectCaught, 'caught all expected errors');
|
|
||||||
process._rawDebug('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Catch synchronous throws
|
|
||||||
errorMsgs.push('sync throw');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
expectCaught++;
|
|
||||||
currentMsg = 'sync throw';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Simple cases
|
|
||||||
errorMsgs.push('setTimeout - simple');
|
|
||||||
errorMsgs.push('setImmediate - simple');
|
|
||||||
errorMsgs.push('setInterval - simple');
|
|
||||||
errorMsgs.push('process.nextTick - simple');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
currentMsg = 'setTimeout - simple';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
setImmediate(function() {
|
|
||||||
currentMsg = 'setImmediate - simple';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
var b = setInterval(function() {
|
|
||||||
clearInterval(b);
|
|
||||||
currentMsg = 'setInterval - simple';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
currentMsg = 'process.nextTick - simple';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Deeply nested
|
|
||||||
errorMsgs.push('setInterval - nested');
|
|
||||||
errorMsgs.push('setImmediate - nested');
|
|
||||||
errorMsgs.push('process.nextTick - nested');
|
|
||||||
errorMsgs.push('setTimeout2 - nested');
|
|
||||||
errorMsgs.push('setTimeout - nested');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
process.nextTick(function() {
|
|
||||||
setImmediate(function() {
|
|
||||||
var b = setInterval(function() {
|
|
||||||
clearInterval(b);
|
|
||||||
currentMsg = 'setInterval - nested';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
currentMsg = 'setImmediate - nested';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
currentMsg = 'process.nextTick - nested';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
setTimeout(function() {
|
|
||||||
currentMsg = 'setTimeout2 - nested';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
currentMsg = 'setTimeout - nested';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// FS
|
|
||||||
errorMsgs.push('fs - file does not exist');
|
|
||||||
errorMsgs.push('fs - exists');
|
|
||||||
errorMsgs.push('fs - realpath');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
fs.stat('does not exist', function(err, stats) {
|
|
||||||
currentMsg = 'fs - file does not exist';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
fs.exists('hi all', function(exists) {
|
|
||||||
currentMsg = 'fs - exists';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
fs.realpath('/some/path', function(err, resolved) {
|
|
||||||
currentMsg = 'fs - realpath';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Nested FS
|
|
||||||
errorMsgs.push('fs - nested file does not exist');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
setImmediate(function() {
|
|
||||||
var b = setInterval(function() {
|
|
||||||
clearInterval(b);
|
|
||||||
process.nextTick(function() {
|
|
||||||
fs.stat('does not exist', function(err, stats) {
|
|
||||||
currentMsg = 'fs - nested file does not exist';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Net
|
|
||||||
errorMsgs.push('net - connection listener');
|
|
||||||
errorMsgs.push('net - client connect');
|
|
||||||
errorMsgs.push('net - server listening');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
var server = net.createServer(function(c) {
|
|
||||||
server.close();
|
|
||||||
currentMsg = 'net - connection listener';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
server.listen(common.PORT, function() {
|
|
||||||
var client = net.connect(common.PORT, function() {
|
|
||||||
client.end();
|
|
||||||
currentMsg = 'net - client connect';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
currentMsg = 'net - server listening';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// DNS
|
|
||||||
errorMsgs.push('dns - lookup');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
dns.lookup('localhost', function() {
|
|
||||||
currentMsg = 'dns - lookup';
|
|
||||||
throw new Error(currentMsg);
|
|
||||||
});
|
|
||||||
expectCaught++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
@ -1,70 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var addListener = tracing.addAsyncListener;
|
|
||||||
var removeListener = tracing.removeAsyncListener;
|
|
||||||
var caught = [];
|
|
||||||
var expect = [];
|
|
||||||
|
|
||||||
var callbacksObj = {
|
|
||||||
error: function(value, er) {
|
|
||||||
process._rawDebug('caught', er.message);
|
|
||||||
caught.push(er.message);
|
|
||||||
return (expect.indexOf(er.message) !== -1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var listener = tracing.createAsyncListener(callbacksObj);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
removeListener(listener);
|
|
||||||
|
|
||||||
if (code > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
expect = expect.sort();
|
|
||||||
caught = caught.sort();
|
|
||||||
|
|
||||||
process._rawDebug('expect', expect);
|
|
||||||
process._rawDebug('caught', caught);
|
|
||||||
assert.deepEqual(caught, expect, 'caught all expected errors');
|
|
||||||
process._rawDebug('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
expect.push('immediate simple a');
|
|
||||||
expect.push('immediate simple b');
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
// Tests for a setImmediate specific bug encountered while implementing
|
|
||||||
// AsyncListeners.
|
|
||||||
setImmediate(function() {
|
|
||||||
throw new Error('immediate simple a');
|
|
||||||
});
|
|
||||||
setImmediate(function() {
|
|
||||||
throw new Error('immediate simple b');
|
|
||||||
});
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
@ -1,47 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
var val;
|
|
||||||
var callbacks = {
|
|
||||||
create: function() {
|
|
||||||
return 42;
|
|
||||||
},
|
|
||||||
before: function() {
|
|
||||||
tracing.removeAsyncListener(listener);
|
|
||||||
tracing.addAsyncListener(listener);
|
|
||||||
},
|
|
||||||
after: function(context, storage) {
|
|
||||||
val = storage;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var listener = tracing.addAsyncListener(callbacks);
|
|
||||||
|
|
||||||
process.nextTick(function() {});
|
|
||||||
|
|
||||||
process.on('exit', function(status) {
|
|
||||||
tracing.removeAsyncListener(listener);
|
|
||||||
assert.equal(status, 0);
|
|
||||||
assert.equal(val, 42);
|
|
||||||
});
|
|
@ -1,53 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
var set = 0;
|
|
||||||
|
|
||||||
var asyncNoHandleError = {
|
|
||||||
before: function() {
|
|
||||||
set++;
|
|
||||||
},
|
|
||||||
after: function() {
|
|
||||||
set++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var key = tracing.addAsyncListener(asyncNoHandleError);
|
|
||||||
|
|
||||||
tracing.removeAsyncListener(key);
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// The async handler should never be called.
|
|
||||||
assert.equal(set, 0);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
var done = false;
|
|
||||||
var callbacks = {
|
|
||||||
before: function() {
|
|
||||||
tracing.removeAsyncListener(listener);
|
|
||||||
},
|
|
||||||
after: function() {
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var listener = tracing.addAsyncListener(callbacks);
|
|
||||||
|
|
||||||
process.nextTick(function() {});
|
|
||||||
|
|
||||||
process.on('exit', function(status) {
|
|
||||||
tracing.removeAsyncListener(listener);
|
|
||||||
assert.equal(status, 0);
|
|
||||||
assert.ok(done);
|
|
||||||
});
|
|
@ -1,58 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var set = 0;
|
|
||||||
var asyncNoHandleError = {
|
|
||||||
error: function() {
|
|
||||||
set++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var key = tracing.addAsyncListener(asyncNoHandleError);
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
throw 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
tracing.removeAsyncListener(key);
|
|
||||||
|
|
||||||
var uncaughtFired = false;
|
|
||||||
process.on('uncaughtException', function() {
|
|
||||||
uncaughtFired = true;
|
|
||||||
|
|
||||||
// Throwing should call the error handler once, then propagate to
|
|
||||||
// uncaughtException
|
|
||||||
assert.equal(set, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
assert.ok(uncaughtFired);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
@ -1,53 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var set = 0;
|
|
||||||
var asyncNoHandleError = {
|
|
||||||
before: function() {
|
|
||||||
set++;
|
|
||||||
},
|
|
||||||
after: function() {
|
|
||||||
set++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var key = tracing.addAsyncListener(asyncNoHandleError);
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
|
|
||||||
tracing.removeAsyncListener(key);
|
|
||||||
|
|
||||||
process.on('exit', function(code) {
|
|
||||||
// If the exit code isn't ok then return early to throw the stack that
|
|
||||||
// caused the bad return code.
|
|
||||||
if (code !== 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Calling removeAsyncListener *after* a callback is scheduled
|
|
||||||
// should not affect the handler from responding to the callback.
|
|
||||||
assert.equal(set, 2);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var net = require('net');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var errMsg = 'net - error: server connection';
|
|
||||||
var cntr = 0;
|
|
||||||
var al = tracing.addAsyncListener({
|
|
||||||
error: function(stor, er) {
|
|
||||||
cntr++;
|
|
||||||
process._rawDebug('Handling error: ' + er.message);
|
|
||||||
assert.equal(errMsg, er.message);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', function(status) {
|
|
||||||
tracing.removeAsyncListener(al);
|
|
||||||
|
|
||||||
console.log('exit status:', status);
|
|
||||||
assert.equal(status, 0);
|
|
||||||
console.log('cntr:', cntr);
|
|
||||||
assert.equal(cntr, 1);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var server = net.createServer(function(c) {
|
|
||||||
this.close();
|
|
||||||
throw new Error(errMsg);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
server.listen(common.PORT, function() {
|
|
||||||
net.connect(common.PORT, function() {
|
|
||||||
this.destroy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,46 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var cntr = 0;
|
|
||||||
var al = tracing.createAsyncListener({
|
|
||||||
create: function() { cntr++; },
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', function() {
|
|
||||||
assert.equal(cntr, 4);
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
tracing.addAsyncListener(al);
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
tracing.addAsyncListener(al);
|
|
||||||
process.nextTick(function() {
|
|
||||||
tracing.addAsyncListener(al);
|
|
||||||
process.nextTick(function() {
|
|
||||||
process.nextTick(function() { });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
// If there is an uncaughtException listener then the error thrown from
|
|
||||||
// "before" will be considered handled, thus calling setImmediate to
|
|
||||||
// finish execution of the nextTickQueue. This in turn will cause "before"
|
|
||||||
// to fire again, entering into an infinite loop.
|
|
||||||
// So the asyncQueue is cleared from the returned setImmediate in
|
|
||||||
// _fatalException to prevent this from happening.
|
|
||||||
var cntr = 0;
|
|
||||||
|
|
||||||
|
|
||||||
tracing.addAsyncListener({
|
|
||||||
before: function() {
|
|
||||||
if (++cntr > 1) {
|
|
||||||
// Can't throw since uncaughtException will also catch that.
|
|
||||||
process._rawDebug('Error: Multiple before callbacks called');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
throw new Error('before');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('uncaughtException', function() { });
|
|
||||||
|
|
||||||
process.nextTick();
|
|
@ -1,188 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var net = require('net');
|
|
||||||
var fs = require('fs');
|
|
||||||
var dgram = require('dgram');
|
|
||||||
var tracing = require('tracing');
|
|
||||||
|
|
||||||
var addListener = tracing.addAsyncListener;
|
|
||||||
var removeListener = tracing.removeAsyncListener;
|
|
||||||
var actualAsync = 0;
|
|
||||||
var expectAsync = 0;
|
|
||||||
|
|
||||||
var callbacks = {
|
|
||||||
create: function onAsync() {
|
|
||||||
actualAsync++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var listener = tracing.createAsyncListener(callbacks);
|
|
||||||
|
|
||||||
process.on('exit', function() {
|
|
||||||
process._rawDebug('expected', expectAsync);
|
|
||||||
process._rawDebug('actual ', actualAsync);
|
|
||||||
// TODO(trevnorris): Not a great test. If one was missed, but others
|
|
||||||
// overflowed then the test would still pass.
|
|
||||||
assert.ok(actualAsync >= expectAsync);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Test listeners side-by-side
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
var b = setInterval(function() {
|
|
||||||
clearInterval(b);
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
var c = setInterval(function() {
|
|
||||||
clearInterval(c);
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
setTimeout(function() { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
setTimeout(function() { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
process.nextTick(function() { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
setImmediate(function() { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
setImmediate(function() { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
setTimeout(function() { }, 10);
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
setTimeout(function() { }, 10);
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Async listeners should propagate with nested callbacks
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
var interval = 3;
|
|
||||||
|
|
||||||
process.nextTick(function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
setImmediate(function() {
|
|
||||||
var i = setInterval(function() {
|
|
||||||
if (--interval <= 0)
|
|
||||||
clearInterval(i);
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
process.nextTick(function() {
|
|
||||||
setImmediate(function() {
|
|
||||||
setTimeout(function() { }, 20);
|
|
||||||
expectAsync++;
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Test triggers with two async listeners
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
process.nextTick(function() { });
|
|
||||||
expectAsync += 2;
|
|
||||||
});
|
|
||||||
expectAsync += 2;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Test callbacks from fs I/O
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
fs.stat('something random', function(err, stat) { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
setImmediate(function() {
|
|
||||||
fs.stat('random again', function(err, stat) { });
|
|
||||||
expectAsync++;
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Test net I/O
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
var server = net.createServer(function(c) { });
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
server.listen(common.PORT, function() {
|
|
||||||
server.close();
|
|
||||||
expectAsync++;
|
|
||||||
});
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Test UDP
|
|
||||||
process.nextTick(function() {
|
|
||||||
addListener(listener);
|
|
||||||
|
|
||||||
var server = dgram.createSocket('udp4');
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
server.bind(common.PORT);
|
|
||||||
|
|
||||||
server.close();
|
|
||||||
expectAsync++;
|
|
||||||
|
|
||||||
removeListener(listener);
|
|
||||||
});
|
|
Loading…
x
Reference in New Issue
Block a user