diff --git a/src/async-wrap-inl.h b/src/async-wrap-inl.h index 388ee19c2bd..324c57b9aef 100644 --- a/src/async-wrap-inl.h +++ b/src/async-wrap-inl.h @@ -101,11 +101,11 @@ inline v8::Handle AsyncWrap::MakeDomainCallback( v8::Local enter = domain->Get(env()->enter_string()).As(); - assert(enter->IsFunction()); - enter->Call(domain, 0, NULL); - - if (try_catch.HasCaught()) - return Undefined(env()->isolate()); + if (enter->IsFunction()) { + enter->Call(domain, 0, NULL); + if (try_catch.HasCaught()) + return Undefined(env()->isolate()); + } } v8::Local ret = cb->Call(context, argc, argv); @@ -117,11 +117,11 @@ inline v8::Handle AsyncWrap::MakeDomainCallback( if (has_domain) { v8::Local exit = domain->Get(env()->exit_string()).As(); - assert(exit->IsFunction()); - exit->Call(domain, 0, NULL); - - if (try_catch.HasCaught()) - return Undefined(env()->isolate()); + if (exit->IsFunction()) { + exit->Call(domain, 0, NULL); + if (try_catch.HasCaught()) + return Undefined(env()->isolate()); + } } if (has_async_listener()) { diff --git a/src/node.cc b/src/node.cc index fe97888e903..d2f9f8b8d2f 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1032,13 +1032,11 @@ Handle MakeDomainCallback(Environment* env, return Undefined(env->isolate()); } - Local enter = - domain->Get(env->enter_string()).As(); - assert(enter->IsFunction()); - enter->Call(domain, 0, NULL); - - if (try_catch.HasCaught()) { - return Undefined(env->isolate()); + Local enter = domain->Get(env->enter_string()).As(); + if (enter->IsFunction()) { + enter->Call(domain, 0, NULL); + if (try_catch.HasCaught()) + return Undefined(env->isolate()); } } } @@ -1050,13 +1048,11 @@ Handle MakeDomainCallback(Environment* env, } if (has_domain) { - Local exit = - domain->Get(env->exit_string()).As(); - assert(exit->IsFunction()); - exit->Call(domain, 0, NULL); - - if (try_catch.HasCaught()) { - return Undefined(env->isolate()); + Local exit = domain->Get(env->exit_string()).As(); + if (exit->IsFunction()) { + exit->Call(domain, 0, NULL); + if (try_catch.HasCaught()) + return Undefined(env->isolate()); } } diff --git a/test/addons/repl-domain-abort/binding.cc b/test/addons/repl-domain-abort/binding.cc new file mode 100644 index 00000000000..1337395c1b9 --- /dev/null +++ b/test/addons/repl-domain-abort/binding.cc @@ -0,0 +1,47 @@ +// 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. + +#include +#include + +using v8::Function; +using v8::FunctionCallbackInfo; +using v8::Handle; +using v8::HandleScope; +using v8::Isolate; +using v8::Object; +using v8::Value; + +void Method(const FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + node::MakeCallback(isolate, + isolate->GetCurrentContext()->Global(), + args[0].As(), + 0, + NULL); +} + +void init(Handle target) { + NODE_SET_METHOD(target, "method", Method); +} + +NODE_MODULE(binding, init); diff --git a/test/addons/repl-domain-abort/binding.gyp b/test/addons/repl-domain-abort/binding.gyp new file mode 100644 index 00000000000..3bfb84493f3 --- /dev/null +++ b/test/addons/repl-domain-abort/binding.gyp @@ -0,0 +1,8 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/test/addons/repl-domain-abort/test.js b/test/addons/repl-domain-abort/test.js new file mode 100644 index 00000000000..c35faafb455 --- /dev/null +++ b/test/addons/repl-domain-abort/test.js @@ -0,0 +1,64 @@ +// 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 assert = require('assert'); +var repl = require('repl'); +var stream = require('stream'); +var buildType = process.config.target_defaults.default_configuration; +var buildPath = __dirname + '/build/' + buildType + '/binding'; +var cb_ran = false; + +process.on('exit', function() { + assert(cb_ran); + console.log('ok'); +}); + +var lines = [ + // This line shouldn't cause an assertion error. + 'require(\'' + buildPath + '\')' + + // Log output to double check callback ran. + '.method(function() { console.log(\'cb_ran\'); });', +]; + +var dInput = new stream.Readable(); +var dOutput = new stream.Writable(); + +dInput._read = function _read(size) { + while (lines.length > 0 && this.push(lines.shift())); + if (lines.length === 0) + this.push(null); +}; + +dOutput._write = function _write(chunk, encoding, cb) { + if (chunk.toString().indexOf('cb_ran') === 0) + cb_ran = true; + cb(); +}; + +var options = { + input: dInput, + output: dOutput, + terminal: false, + ignoreUndefined: true +}; + +// Run commands from fake REPL. +var dummy = repl.start(options);