Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

async-listener

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

async-listener - npm Package Compare versions

Comparing version 0.4.0 to 0.4.1

test/core-asynclistener-duplicate.simple.js

362

glue.js

@@ -24,18 +24,2 @@ var wrap = require('shimmer').wrap;

/**
* Error handlers on listeners can throw, the the catcher needs to be able to
* discriminate between exceptions thrown by user code, and exceptions coming
* from within the catcher itself. Use a global to keep track of which state
* the catcher is currently in.
*/
var inErrorTick = false;
/**
* Throwing always happens synchronously. If the current array of values for
* the current list of asyncListeners is put in a module-scoped variable right
* before a call that can throw, it will always be correct when the error
* handlers are run.
*/
var errorValues;
/**
* Because asynchronous contexts can be nested, and errors can come from anywhere

@@ -55,47 +39,10 @@ * in the stack, a little extra work is required to keep track of where in the

*/
function asyncCatcher(er) {
var length = listeners.length;
if (inErrorTick || length === 0) return false;
var asyncCatcher;
var handled = false;
/**
* The guts of the system -- called each time an asynchronous event happens
* while one or more listeners are active.
*/
var asyncWrap;
/*
* error handlers
*/
inErrorTick = true;
for (var i = 0; i < length; ++i) {
if (!listeners[i].callbacks) continue;
var error = listeners[i].callbacks.error;
var value = errorValues && errorValues[i];
if (typeof error === 'function') handled = error(value, er) || handled;
}
inErrorTick = false;
/* Test whether there are any listener arrays on the stack. In the case of
* synchronous throws when the listener is active, there may have been
* none pushed yet.
*/
if (listenerStack.length > 0) listeners = listenerStack.pop();
errorValues = undefined;
return handled && !inAsyncTick;
}
// 0.9+
if (process._fatalException) {
wrap(process, '_fatalException', function (_fatalException) {
return function _asyncFatalException(er) {
return asyncCatcher(er) || _fatalException(er);
};
});
}
// 0.8 and below
else {
// will be the first to fire if async-listener is the first module loaded
process.on('uncaughtException', function _asyncUncaughtException(er) {
return asyncCatcher(er) || false;
});
}
/**

@@ -105,3 +52,5 @@ * Simple helper function that's probably faster than using Array

*/
function union(dest, destLength, added, addedLength) {
function union(dest, added) {
var destLength = dest.length;
var addedLength = added.length;
var returned = [];

@@ -128,73 +77,272 @@

}
/**
* The guts of the system -- called each time an asynchronous event happens
* while one or more listeners are active.
/*
* For performance, split error-handlers and asyncCatcher up into two separate
* code paths.
*/
function asyncWrap(original, list, length) {
var values = [];
/*
* listeners
// 0.9+
if (process._fatalException) {
/**
* Error handlers on listeners can throw, the the catcher needs to be able to
* discriminate between exceptions thrown by user code, and exceptions coming
* from within the catcher itself. Use a global to keep track of which state
* the catcher is currently in.
*/
inAsyncTick = true;
for (var i = 0; i < length; ++i) {
/* asyncListener.domain is the default value passed through before and
* after if the listener doesn't return a value.
*/
values[i] = list[i].domain;
var value = list[i].listener.call(this);
if (typeof value !== 'undefined') values[i] = value;
}
inAsyncTick = false;
var inErrorTick = false;
/* One of the main differences between this polyfill and the core
* asyncListener support is that core avoids creating closures by putting a
* lot of the state managemnt on the C++ side of Node (and of course also it
* bakes support for async listeners into the Node C++ API through the
* AsyncWrap class, which means that it doesn't monkeypatch basically every
* async method like this does).
/**
* Throwing always happens synchronously. If the current array of values for
* the current list of asyncListeners is put in a module-scoped variable right
* before a call that can throw, it will always be correct when the error
* handlers are run.
*/
return function () {
var errorValues;
asyncCatcher = function asyncCatcher(er) {
var length = listeners.length;
if (inErrorTick || length === 0) return false;
var handled = false;
/*
* before handlers
* error handlers
*/
inErrorTick = true;
for (var i = 0; i < length; ++i) {
if (!listeners[i].callbacks) continue;
var error = listeners[i].callbacks.error;
var value = errorValues && errorValues[i];
if (typeof error === 'function') handled = error(value, er) || handled;
}
inErrorTick = false;
/* Test whether there are any listener arrays on the stack. In the case of
* synchronous throws when the listener is active, there may have been
* none pushed yet.
*/
if (listenerStack.length > 0) listeners = listenerStack.pop();
errorValues = undefined;
return handled && !inAsyncTick;
};
asyncWrap = function asyncWrap(original, list, length) {
var values = [];
/*
* listeners
*/
inAsyncTick = true;
for (var i = 0; i < length; ++i) {
var before = list[i].callbacks && list[i].callbacks.before;
if (typeof before === 'function') before(this, values[i]);
/* asyncListener.domain is the default value passed through before and
* after if the listener doesn't return a value.
*/
values[i] = list[i].domain;
var value = list[i].listener.call(this);
if (typeof value !== 'undefined') values[i] = value;
}
inAsyncTick = false;
// put the current values where the catcher can see them
errorValues = values;
/* One of the main differences between this polyfill and the core
* asyncListener support is that core avoids creating closures by putting a
* lot of the state managemnt on the C++ side of Node (and of course also it
* bakes support for async listeners into the Node C++ API through the
* AsyncWrap class, which means that it doesn't monkeypatch basically every
* async method like this does).
*/
return function () {
/* More than one listener can end up inside these closures, so save the
* current listeners on a stack.
// put the current values where the catcher can see them
errorValues = values;
/* More than one listener can end up inside these closures, so save the
* current listeners on a stack.
*/
listenerStack.push(listeners);
/* Activate both the listeners that were active when the closure was
* created and the listeners that were previously active.
*/
listeners = union(list, listeners);
/*
* before handlers
*/
inAsyncTick = true;
for (var i = 0; i < length; ++i) {
var before = list[i].callbacks && list[i].callbacks.before;
if (typeof before === 'function') before(this, values[i]);
}
inAsyncTick = false;
// save the return value to pass to the after callbacks
var returned = original.apply(this, arguments);
/*
* after handlers (not run if original throws)
*/
inAsyncTick = true;
for (i = 0; i < length; ++i) {
var after = list[i].callbacks && list[i].callbacks.after;
if (typeof after === 'function') after(this, values[i], returned);
}
inAsyncTick = false;
// back to the previous listener list on the stack
listeners = listenerStack.pop();
errorValues = undefined;
return returned;
};
};
wrap(process, '_fatalException', function (_fatalException) {
return function _asyncFatalException(er) {
return asyncCatcher(er) || _fatalException(er);
};
});
}
// 0.8 and below
else {
/**
* The error handler in the error-checker for old Node must rethrow to give
* domains and other uncaughtException handlers a chance to fire, but there's
* nothing for the uncaughtException handler to do.
*/
var threw = false;
/**
* If an error handler in asyncWrap throws, the process must die. Under 0.8
* and earlier the only way to put a bullet through the head of the process
* is to rethrow from inside the exception handler, so rethrow and set
* errorThrew to tell the uncaughtHandler what to do.
*/
var errorThrew = false;
/**
* Under Node 0.8, this handler *only* handles synchronously thrown errors.
* This simplifies it, which almost but not quite makes up for the hit taken
* by putting everything in a try-catch.
*/
asyncCatcher = function uncaughtCatcher(er) {
if (threw) {
threw = false;
return;
}
// going down hard
if (errorThrew) throw er;
var handled = false;
/*
* error handlers
*/
listenerStack.push(listeners);
var length = listeners.length;
for (var i = 0; i < length; ++i) {
var error = listeners[i].callbacks && listeners[i].callbacks.error;
if (typeof error === 'function') handled = error(undefined, er) || handled;
}
/* Activate both the listeners that were active when the closure was
* created and the listeners that were previously active.
/* Rethrow if one of the before / after handlers fire, which will bring the
* process down immediately.
*/
listeners = union(list, length, listeners, listeners.length);
if (!handled && inAsyncTick) throw er;
};
// save the return value to pass to the after callbacks
var returned = original.apply(this, arguments);
asyncWrap = function asyncWrap(original, list, length) {
var values = [];
// back to the previous listener list on the stack
listeners = listenerStack.pop();
errorValues = undefined;
/*
* after handlers (not run if original throws)
* listeners
*/
inAsyncTick = true;
for (i = 0; i < length; ++i) {
var after = list[i].callbacks && list[i].callbacks.after;
if (typeof after === 'function') after(this, values[i], returned);
for (var i = 0; i < length; ++i) {
/* asyncListener.domain is the default value passed through before and
* after if the listener doesn't return a value.
*/
values[i] = list[i].domain;
var value = list[i].listener.call(this);
if (typeof value !== 'undefined') values[i] = value;
}
inAsyncTick = false;
return returned;
/* One of the main differences between this polyfill and the core
* asyncListener support is that core avoids creating closures by putting a
* lot of the state managemnt on the C++ side of Node (and of course also it
* bakes support for async listeners into the Node C++ API through the
* AsyncWrap class, which means that it doesn't monkeypatch basically every
* async method like this does).
*/
return function () {
/* More than one listener can end up inside these closures, so save the
* current listeners on a stack.
*/
listenerStack.push(listeners);
/* Activate both the listeners that were active when the closure was
* created and the listeners that were previously active.
*/
listeners = union(list, listeners);
/*
* before handlers
*/
inAsyncTick = true;
for (var i = 0; i < length; ++i) {
var before = list[i].callbacks && list[i].callbacks.before;
if (typeof before === 'function') before(this, values[i]);
}
inAsyncTick = false;
// save the return value to pass to the after callbacks
var returned;
try {
returned = original.apply(this, arguments);
}
catch (er) {
var handled = false;
for (var i = 0; i < length; ++i) {
var error = listeners[i].callbacks.error;
if (typeof error === 'function') {
try {
handled = error(values[i], er) || handled;
}
catch (x) {
errorThrew = true;
throw x;
}
}
}
// back to the previous listener list on the stack
listeners = listenerStack.pop();
if (handled) return;
threw = true;
throw er;
}
/*
* after handlers (not run if original throws)
*/
inAsyncTick = true;
for (i = 0; i < length; ++i) {
var after = list[i].callbacks && list[i].callbacks.after;
if (typeof after === 'function') after(this, values[i], returned);
}
inAsyncTick = false;
// back to the previous listener list on the stack
listeners = listenerStack.pop();
return returned;
};
};
// will be the first to fire if async-listener is the first module loaded
process.on('uncaughtException', asyncCatcher);
}

@@ -212,3 +360,3 @@

listenerStack.push(listeners);
listeners = union(list, length, listeners, listeners.length);
listeners = union(list, listeners);

@@ -215,0 +363,0 @@ var returned = original.apply(this, arguments);

{
"name": "async-listener",
"version": "0.4.0",
"version": "0.4.1",
"description": "Polyfill exporting trevnorris's 0.11+ asyncListener API.",

@@ -5,0 +5,0 @@ "author": "Forrest L Norvell <ogd@aoaioxxysz.net>",

@@ -25,2 +25,3 @@ // Copyright Joyent, Inc. and other Node contributors.

if (!process.addAsyncListener) require('../index.js');
if (!global.setImmediate) global.setImmediate = setTimeout;

@@ -27,0 +28,0 @@ var assert = require('assert');

@@ -25,2 +25,3 @@ // Copyright Joyent, Inc. and other Node contributors.

if (!process.addAsyncListener) require('../index.js');
if (!global.setImmediate) global.setImmediate = setTimeout;

@@ -27,0 +28,0 @@ var assert = require('assert');

var test = require('tap').test;
if (!global.setImmediate) global.setImmediate = setTimeout;
test("after handler not run on throw", function (t) {

@@ -4,0 +6,0 @@ t.plan(2);

@@ -5,2 +5,4 @@ var test = require('tap').test

if (!global.setImmediate) global.setImmediate = setTimeout;
/**

@@ -7,0 +9,0 @@ *

var test = require('tap').test;
if (!global.setImmediate) global.setImmediate = setTimeout;
test("asyncListeners work as expected with process.nextTick", function (t) {

@@ -4,0 +6,0 @@ t.plan(1);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc