Fix for AVATAR_JS-95, support for domains

reviewed-by: asquare
This commit is contained in:
Jean-Francois 2013-12-05 11:48:05 +01:00
parent 513b1208c7
commit d00cde3964
9 changed files with 389 additions and 75 deletions

View File

@ -285,6 +285,7 @@
<apply-diff src="test/simple" mod="${test.dir}/simple" name="test-dgram-ref.js"/>
<apply-diff src="test/simple" mod="${test.dir}/simple" name="test-dgram-udp4.js"/>
<apply-diff src="test/simple" mod="${test.dir}/simple" name="test-dgram-unref.js"/>
<apply-diff src="test/simple" mod="${test.dir}/simple" name="test-domain.js"/>
<apply-diff src="test/simple" mod="${test.dir}/simple" name="test-error-reporting.js"/>
<apply-diff src="test/simple" mod="${test.dir}/simple" name="test-fs-read-stream.js"/>
<apply-diff src="test/simple" mod="${test.dir}/simple" name="test-fs-readfile-pipe.js"/>
@ -361,6 +362,7 @@
<apply-patch-file target="${test.dir}/simple" dir="test/simple" name="test-dgram-ref.js"/>
<apply-patch-file target="${test.dir}/simple" dir="test/simple" name="test-dgram-udp4.js"/>
<apply-patch-file target="${test.dir}/simple" dir="test/simple" name="test-dgram-unref.js"/>
<apply-patch-file target="${test.dir}/simple" dir="test/simple" name="test-domain.js"/>
<apply-patch-file target="${test.dir}/simple" dir="test/simple" name="test-error-reporting.js"/>
<apply-patch-file target="${test.dir}/simple" dir="test/simple" name="test-fs-read-stream.js"/>
<apply-patch-file target="${test.dir}/simple" dir="test/simple" name="test-fs-readfile-pipe.js"/>

View File

@ -0,0 +1,29 @@
--- ../node/test/simple/test-domain.js 2013-08-22 13:48:54.000000000 +0200
+++ test/simple/test-domain.js 2013-12-04 14:07:46.000000000 +0100
@@ -70,7 +70,7 @@
assert.equal(er.domainThrown, true);
break;
- case "ENOENT, open 'this file does not exist'":
+ case "ENOENT, no such file or directory 'this file does not exist'":
assert.equal(er.domain, d);
assert.equal(er.domainThrown, false);
assert.equal(typeof er.domainBound, 'function');
@@ -80,7 +80,7 @@
assert.equal(typeof er.errno, 'number');
break;
- case "ENOENT, open 'stream for nonexistent file'":
+ case "ENOENT, no such file or directory 'stream for nonexistent file'":
assert.equal(typeof er.errno, 'number');
assert.equal(er.code, 'ENOENT');
assert.equal(er_path, 'stream for nonexistent file');
@@ -104,7 +104,7 @@
assert.ok(!er.domainBound);
break;
- case 'Cannot call method \'isDirectory\' of undefined':
+ case 'Cannot read property "isDirectory" from undefined':
assert.equal(er.domain, d);
assert.ok(!er.domainEmitter);
assert.ok(!er.domainBound);

View File

@ -142,6 +142,17 @@ source.test.simple.list = \
test-dgram-send-bad-arguments.js \
test-dgram-udp4.js \
test-dgram-unref.js \
test-domain-crypto.js \
test-domain-exit-dispose.js \
test-domain-from-timer.js \
test-domain-http-server.js \
test-domain-implicit-fs.js \
test-domain-multi.js \
test-domain-nested-throw.js \
test-domain-nested.js \
test-domain-stack.js \
test-domain-timers.js \
test-domain.js \
test-error-reporting.js \
test-event-emitter-add-listeners.js \
test-event-emitter-check-listener-leaks.js \

View File

@ -27,8 +27,8 @@ package net.java.avatar.js.eventloop;
import java.security.AccessControlContext;
import java.security.AccessController;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import net.java.avatar.js.eventloop.Callback;
import net.java.avatar.js.Server;
public final class Event {
@ -37,12 +37,15 @@ public final class Event {
private final Callback callback;
private final Object[] args;
private final AccessControlContext ctx;
public Event(final String name, final Callback callback) {
this(name, callback, (Object[]) null);
private final ScriptObjectMirror domain;
public Event(final String name, final ScriptObjectMirror domain, final Callback callback) {
this(name, domain, callback, (Object[]) null);
}
public Event(final String name, final Callback callback, final Object arg) {
public Event(final String name, final ScriptObjectMirror domain, final Callback callback, final Object arg) {
this.name = name;
this.domain = domain;
this.callback = callback;
this.args = new Object[1];
this.args[0] = arg;
@ -55,6 +58,7 @@ public final class Event {
public Event(final String name, final Callback callback, final Object... args) {
this.name = name;
this.domain = null;
this.callback = callback;
this.args = args == null ? null : args.clone();
if(System.getSecurityManager() != null) {
@ -107,4 +111,7 @@ public final class Event {
return sb.toString();
}
public ScriptObjectMirror getDomain() {
return domain;
}
}

View File

@ -41,12 +41,16 @@ import javax.script.ScriptException;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import net.java.avatar.js.dns.DNS;
import net.java.avatar.js.log.Logger;
import net.java.avatar.js.log.Logging;
import net.java.libuv.LibUV;
import net.java.libuv.cb.AsyncCallback;
import net.java.libuv.cb.CallbackExceptionHandler;
import net.java.libuv.cb.CallbackDomainProvider;
import net.java.libuv.cb.CallbackHandler;
import net.java.libuv.cb.CallbackHandlerFactory;
import net.java.libuv.handles.AsyncHandle;
import net.java.libuv.handles.LoopHandle;
@ -69,6 +73,8 @@ public final class EventLoop {
private Callback uncaughtExceptionHandler = null;
private Exception pendingException = null;
private ScriptObjectMirror domain;
public static final class Handle implements AutoCloseable {
private final AtomicInteger hooks;
@ -106,9 +112,14 @@ public final class EventLoop {
uncaughtExceptionHandler = handler;
}
public void nextTick(final Event event) {
public void nextTick(final Callback cb) {
assert Thread.currentThread() == mainThread : "called from non-event thread " + Thread.currentThread().getName();
eventQueue.add(event);
eventQueue.add(new Event("nextTick", cb));
}
public void nextTickWithDomain(final Callback cb, ScriptObjectMirror evtDomain) {
assert Thread.currentThread() == mainThread : "called from non-event thread " + Thread.currentThread().getName();
eventQueue.add(new Event("nextTickWithDomain", evtDomain, cb));
}
public void post(final Callback cb, Object... args) {
@ -141,7 +152,17 @@ public final class EventLoop {
for (Event event = eventQueue.poll();
event != null;
event = eventQueue.poll()) {
processEvent(event);
ScriptObjectMirror evtDomain = event.getDomain();
if (evtDomain != null) {
if (isDisposed(evtDomain)) {
continue;
}
enterDomain(evtDomain);
processEvent(event);
exitDomain(evtDomain);
} else {
processEvent(event);
}
}
}
}
@ -198,19 +219,25 @@ public final class EventLoop {
private static final String UNCAUGHT_EXCEPTION_NAME = "uncaughtException";
public boolean handleCallbackException(final Exception ex) {
boolean handled = true;
// callback to check if an uncaught exception handler has been registered by the user
final Object[] registeredArgs = {null};
if (isHandlerRegistered != null) {
try {
isHandlerRegistered.call(UNCAUGHT_EXCEPTION_NAME, registeredArgs);
} catch (final Exception e) {
return false;
handled = false;
}
}
if (registeredArgs[0] == null || uncaughtExceptionHandler == null) {
// no handler registered - rethrow uncaught exceptions
handled = false;
}
if (!handled && domain == null) {
// No domain and no uncaughtException Handler registered
// rethrowing
return false;
}
@ -333,6 +360,8 @@ public final class EventLoop {
this.uvVersion = uvVersion;
this.logging = logging;
this.dns = new DNS(this);
final LoopCallbackHandler defaultHandler = new LoopCallbackHandler(this);
this.uvLoop = new LoopHandle(new CallbackExceptionHandler() {
@Override
public void handle(final Exception ex) {
@ -345,8 +374,23 @@ public final class EventLoop {
stop();
}
}
}, new LoopCallbackHandler(this));
},
new CallbackHandlerFactory() {
@Override
public CallbackHandler newCallbackHandlerWithDomain(Object domain) {
return new LoopCallbackHandler(EventLoop.this, domain);
}
@Override
public CallbackHandler newCallbackHandler() {
return defaultHandler;
}
},
new CallbackDomainProvider() {
@Override
public Object getDomain() {
return EventLoop.this.getDomain();
}
});
this.instanceNumber = instanceNumber;
this.executor = executor;
@ -399,4 +443,47 @@ public final class EventLoop {
return uvLoop;
}
public void setDomain(ScriptObjectMirror obj) {
assert Thread.currentThread() == mainThread : "called from non-event thread " + Thread.currentThread().getName();
domain = obj;
}
public ScriptObjectMirror getDomain() {
assert Thread.currentThread() == mainThread : "called from non-event thread " + Thread.currentThread().getName();
return domain;
}
public boolean isDisposed(ScriptObjectMirror domain) {
assert Thread.currentThread() == mainThread : "called from non-event thread " + Thread.currentThread().getName();
return Boolean.TRUE.equals(domain.getMember("_disposed"));
}
public void enterDomain(ScriptObjectMirror domain) {
assert Thread.currentThread() == mainThread : "called from non-event thread " + Thread.currentThread().getName();
domain.callMember("enter");
}
public void exitDomain(ScriptObjectMirror domain) {
assert Thread.currentThread() == mainThread : "called from non-event thread " + Thread.currentThread().getName();
domain.callMember("exit");
}
public boolean isDisposed(Object domain) {
if (domain instanceof ScriptObjectMirror) {
isDisposed((ScriptObjectMirror) domain);
}
return false;
}
public void enterDomain(Object domain) {
if (domain instanceof ScriptObjectMirror) {
enterDomain((ScriptObjectMirror) domain);
}
}
public void exitDomain(Object domain) {
if (domain instanceof ScriptObjectMirror) {
exitDomain((ScriptObjectMirror) domain);
}
}
}

View File

@ -63,16 +63,42 @@ import net.java.libuv.cb.UDPSendCallback;
final class LoopCallbackHandler implements CallbackHandler {
private final EventLoop eventLoop;
private final Object domain;
public LoopCallbackHandler(EventLoop eventLoop) {
this(eventLoop, null);
}
public LoopCallbackHandler(EventLoop eventLoop, Object domain) {
this.eventLoop = eventLoop;
this.domain = domain;
}
private boolean shouldCall() {
if (domain != null) {
if (eventLoop.isDisposed(domain)) {
return false;
}
eventLoop.enterDomain(domain);
}
return true;
}
private void post() throws Exception {
if (domain != null) {
eventLoop.exitDomain(domain);
}
eventLoop.processQueuedEvents();
}
@Override
public void handleAsyncCallback(final AsyncCallback cb, final int status) {
try {
cb.onSend(status);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onSend(status);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -81,8 +107,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleCheckCallback(final CheckCallback cb, final int status) {
try {
cb.onCheck(status);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onCheck(status);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -91,8 +119,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleSignalCallback(final SignalCallback cb, final int signum) {
try {
cb.onSignal(signum);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onSignal(signum);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -101,8 +131,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleStreamReadCallback(final StreamReadCallback cb, final ByteBuffer data) {
try {
cb.onRead(data);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onRead(data);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -111,8 +143,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleStreamRead2Callback(final StreamRead2Callback cb, final ByteBuffer data, final long handle, final int type) {
try {
cb.onRead2(data, handle, type);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onRead2(data, handle, type);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -121,8 +155,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleStreamWriteCallback(final StreamWriteCallback cb, final int status, final Exception error) {
try {
cb.onWrite(status, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onWrite(status, error);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -131,8 +167,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleStreamConnectCallback(final StreamConnectCallback cb, final int status, final Exception error) {
try {
cb.onConnect(status, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onConnect(status, error);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -141,8 +179,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleStreamConnectionCallback(final StreamConnectionCallback cb, final int status, final Exception error) {
try {
cb.onConnection(status, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onConnection(status, error);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -151,8 +191,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleStreamCloseCallback(final StreamCloseCallback cb) {
try {
cb.onClose();
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onClose();
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -161,8 +203,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleStreamShutdownCallback(final StreamShutdownCallback cb, final int status, final Exception error) {
try {
cb.onShutdown(status, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onShutdown(status, error);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -171,8 +215,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileCallback(final FileCallback cb, final Object context, final Exception error) {
try {
cb.onDone(context, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onDone(context, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -182,8 +228,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileCloseCallback(final FileCloseCallback cb, final Object context, final int fd, final Exception error) {
try {
cb.onClose(context, fd, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onClose(context, fd, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -192,8 +240,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileOpenCallback(final FileOpenCallback cb, final Object context, final int fd, final Exception error) {
try {
cb.onOpen(context, fd, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onOpen(context, fd, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -202,8 +252,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileReadCallback(final FileReadCallback cb, final Object context, final int bytesRead, final ByteBuffer data, final Exception error) {
try {
cb.onRead(context, bytesRead, data, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onRead(context, bytesRead, data, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -212,8 +264,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileReadDirCallback(final FileReadDirCallback cb, final Object context, final String[] names, final Exception error) {
try {
cb.onReadDir(context, names, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onReadDir(context, names, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -222,8 +276,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileReadLinkCallback(final FileReadLinkCallback cb, final Object context, final String name, final Exception error) {
try {
cb.onReadLink(context, name, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onReadLink(context, name, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -232,8 +288,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileStatsCallback(final FileStatsCallback cb, final Object context, final Stats stats, final Exception error) {
try {
cb.onStats(context, stats, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onStats(context, stats, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -242,8 +300,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileUTimeCallback(final FileUTimeCallback cb, final Object context, final long time, final Exception error) {
try {
cb.onUTime(context, time, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onUTime(context, time, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -252,8 +312,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileWriteCallback(final FileWriteCallback cb, final Object context, final int bytesWritten, final Exception error) {
try {
cb.onWrite(context, bytesWritten, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onWrite(context, bytesWritten, error);
post();
}
} catch (final Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -262,8 +324,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFileEventCallback(FileEventCallback cb, int status, String event, String filename) {
try {
cb.onEvent(status, event, filename);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onEvent(status, event, filename);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -273,7 +337,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFilePollCallback(FilePollCallback cb, int status, Stats previous, Stats current) {
try {
cb.onPoll(status, previous, current);
if (shouldCall()) {
cb.onPoll(status, previous, current);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -282,7 +349,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleFilePollStopCallback(FilePollStopCallback cb) {
try {
cb.onStop();
if (shouldCall()) {
cb.onStop();
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -291,7 +361,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleProcessCloseCallback(ProcessCloseCallback cb) {
try {
cb.onClose();
if (shouldCall()) {
cb.onClose();
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -300,7 +373,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleProcessExitCallback(ProcessExitCallback cb, int status, int signal, Exception error) {
try {
cb.onExit(status, signal, error);
if (shouldCall()) {
cb.onExit(status, signal, error);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -309,8 +385,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleTimerCallback(final TimerCallback cb, final int status) {
try {
cb.onTimer(status);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onTimer(status);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -319,8 +397,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleUDPRecvCallback(final UDPRecvCallback cb, final int nread, final ByteBuffer data, final Address address) {
try {
cb.onRecv(nread, data, address);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onRecv(nread, data, address);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -329,8 +409,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleUDPSendCallback(final UDPSendCallback cb, final int status, final Exception error) {
try {
cb.onSend(status, error);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onSend(status, error);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -339,8 +421,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleUDPCloseCallback(final UDPCloseCallback cb) {
try {
cb.onClose();
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onClose();
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}
@ -349,8 +433,10 @@ final class LoopCallbackHandler implements CallbackHandler {
@Override
public void handleIdleCallback(IdleCallback cb, int status) {
try {
cb.onIdle(status);
eventLoop.processQueuedEvents();
if (shouldCall()) {
cb.onIdle(status);
post();
}
} catch (Exception ex) {
eventLoop.loop().getExceptionHandler().handle(ex);
}

View File

@ -61,7 +61,6 @@ var eventloop = __avatar.eventloop;
var LibUV = Packages.net.java.libuv.LibUV;
var Process = Packages.net.java.avatar.js.os.Process;
var Server = Packages.net.java.avatar.js.Server;
var Event = Packages.net.java.avatar.js.eventloop.Event
var Constants = Packages.net.java.avatar.js.constants.Constants;
var Signals = Packages.net.java.libuv.handles.SignalHandle;
@ -430,16 +429,14 @@ Object.defineProperty(exports, 'hrtime', {
Object.defineProperty(exports, 'nextTick', {
enumerable: true,
configurable: true,
value: function(callback) {
if (this._exiting) {
return;
}
eventloop.nextTick(
new Event('nextTick', function(name, args) {
callback();
}
)
);
eventloop.nextTick(function(name, args) {
callback();
});
}
});
@ -588,8 +585,36 @@ exports.openStdin = function() {
}
exports._usingDomains = function() {
// redefine nextTick at this time to speedup
// domain event posting
Object.defineProperty(exports, 'nextTick', {
enumerable: true,
value: function(callback) {
if (this._exiting) {
return;
}
eventloop.nextTickWithDomain(function(name, args) {
callback();
}, process.domain)
}
});
}
var ScriptUtils = Packages.jdk.nashorn.api.scripting.ScriptUtils
Object.defineProperty(exports, 'domain', {
enumerable : true,
set : function(domain) {
if (domain) {
eventloop.domain = domain;
} else {
eventloop.domain = null;
}
},
get : function() {
return ScriptUtils.unwrap(eventloop.domain);
}
});
var Check = Packages.net.java.libuv.handles.CheckHandle;
var Idle = Packages.net.java.libuv.handles.IdleHandle;
var checkHandle = new Check(eventloop.loop());

View File

@ -200,6 +200,67 @@ var gc = global.gc;
console.log(this.stack);
};
var fatalProcessing = function(er) {
var caught = false;
if (process.domain) { // From nodejs
var domain = process.domain;
var domainModule = NativeModule.require('domain');
var domainStack = domainModule._stack;
// ignore errors on disposed domains.
//
// XXX This is a bit stupid. We should probably get rid of
// domain.dispose() altogether. It's almost always a terrible
// idea. --isaacs
if (domain._disposed)
return true;
er.domain = domain;
er.domainThrown = true;
// wrap this in a try/catch so we don't get infinite throwing
try {
// One of three things will happen here.
//
// 1. There is a handler, caught = true
// 2. There is no handler, caught = false
// 3. It throws, caught = false
//
// If caught is false after this, then there's no need to exit()
// the domain, because we're going to crash the process anyway.
caught = domain.emit('error', er);
// Exit all domains on the stack. Uncaught exceptions end the
// current tick and no domains should be left on the stack
// between ticks.
var domainModule = NativeModule.require('domain');
domainStack.length = 0;
domainModule.active = process.domain = null;
} catch (er2) {
// The domain error handler threw! oh no!
// See if another domain can catch THIS error,
// or else crash on the original one.
// If the user already exited it, then don't double-exit.
if (domain === domainModule.active)
domainStack.pop();
if (domainStack.length) {
var parentDomain = domainStack[domainStack.length - 1];
process.domain = domainModule.active = parentDomain;
caught = fatalProcessing(er2);
} else
caught = false;
}
} else {
caught = process.emit('uncaughtException', er);
}
// Avatar-js specific handling,
// exit is handled in the class that is catching the rethrown er
if (!caught) {
throw er;
}
return caught;
};
__avatar.eventloop.setUncaughtExceptionHandler(
function(name, args) {
var listeners = process.listeners('uncaughtException');
@ -208,13 +269,12 @@ var gc = global.gc;
}
},
function(name, args) {
var ctx = Packages.net.java.avatar.js.eventloop.EventLoop;
var e = new Error();
var ex = args[0];
for (var k in ex) {
e[k] = ex[k];
}
process.emit(name, e);
fatalProcessing(e);
}
);

View File

@ -32,7 +32,14 @@
var that = this;
this._timer.setTimerFiredCallback(function(status) {
if (that.ontimeout) {
// When a timer is unref, the domain is set on the wrap.
if (that.domain) {
that.domain.enter();
}
that.ontimeout();
if (that.domain) {
that.domain.exit();
}
}
});
}