inline HandleWrapQueue* handle_wrap_queue() { return &handle_wrap_queue_; }
inline ReqWrapQueue* req_wrap_queue() { return &req_wrap_queue_; }
+ static const int kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX;
+
private:
static const int kIsolateSlot = NODE_ISOLATE_SLOT;
inline ~Environment();
inline IsolateData* isolate_data() const;
- enum ContextEmbedderDataIndex {
- kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX
- };
-
v8::Isolate* const isolate_;
IsolateData* const isolate_data_;
uv_check_t immediate_check_handle_;
static void RunInDebugContext(const FunctionCallbackInfo<Value>& args) {
+ // Ensure that the debug context has an Environment assigned in case
+ // a fatal error is raised. The fatal exception handler in node.cc
+ // is not equipped to deal with contexts that don't have one and
+ // can't easily be taught that due to a deficiency in the V8 API:
+ // there is no way for the embedder to tell if the data index is
+ // in use.
+ struct ScopedEnvironment {
+ ScopedEnvironment(Local<Context> context, Environment* env)
+ : context_(context) {
+ const int index = Environment::kContextEmbedderDataIndex;
+ context->SetAlignedPointerInEmbedderData(index, env);
+ }
+ ~ScopedEnvironment() {
+ const int index = Environment::kContextEmbedderDataIndex;
+ context_->SetAlignedPointerInEmbedderData(index, nullptr);
+ }
+ Local<Context> context_;
+ };
+
Local<String> script_source(args[0]->ToString(args.GetIsolate()));
if (script_source.IsEmpty())
return; // Exception pending.
- Context::Scope context_scope(Debug::GetDebugContext());
+ Local<Context> debug_context = Debug::GetDebugContext();
+ Environment* env = Environment::GetCurrent(args);
+ ScopedEnvironment env_scope(debug_context, env);
+ Context::Scope context_scope(debug_context);
Local<Script> script = Script::Compile(script_source);
if (script.IsEmpty())
return; // Exception pending.
--- /dev/null
+if (process.argv[2] === 'handle-fatal-exception')
+ process._fatalException = process.exit.bind(null, 42);
+
+require('vm').runInDebugContext('*');
var common = require('../common');
var assert = require('assert');
var vm = require('vm');
+var spawn = require('child_process').spawn;
assert.throws(function() {
vm.runInDebugContext('*');
assert.strictEqual(vm.runInDebugContext(0), 0);
assert.strictEqual(vm.runInDebugContext(null), null);
assert.strictEqual(vm.runInDebugContext(undefined), undefined);
+
+// See https://github.com/iojs/io.js/issues/1190, fatal errors should not
+// crash the process.
+var script = common.fixturesDir + '/vm-run-in-debug-context.js';
+var proc = spawn(process.execPath, [script]);
+var data = [];
+proc.stdout.on('data', assert.fail);
+proc.stderr.on('data', data.push.bind(data));
+proc.once('exit', common.mustCall(function(exitCode, signalCode) {
+ assert.equal(exitCode, 1);
+ assert.equal(signalCode, null);
+ var haystack = Buffer.concat(data).toString('utf8');
+ assert(/SyntaxError: Unexpected token \*/.test(haystack));
+}));
+
+var proc = spawn(process.execPath, [script, 'handle-fatal-exception']);
+proc.stdout.on('data', assert.fail);
+proc.stderr.on('data', assert.fail);
+proc.once('exit', common.mustCall(function(exitCode, signalCode) {
+ assert.equal(exitCode, 42);
+ assert.equal(signalCode, null);
+}));