Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 22cd537

Browse filesBrowse files
devsnektargos
authored andcommitted
lib: trigger uncaught exception handler for microtasks
PR-URL: #23794 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matheus Marchini <mat@mmarchini.me>
1 parent b07cb48 commit 22cd537
Copy full SHA for 22cd537

File tree

Expand file treeCollapse file tree

5 files changed

+52
-25
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

5 files changed

+52
-25
lines changed
Open diff view settings
Collapse file

‎doc/api/globals.md‎

Copy file name to clipboardExpand all lines: doc/api/globals.md
+2-2Lines changed: 2 additions & 2 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ added: v11.0.0
119119
* `callback` {Function} Function to be queued.
120120

121121
The `queueMicrotask()` method queues a microtask to invoke `callback`. If
122-
`callback` throws an exception, the [`process` object][] `'error'` event will
123-
be emitted.
122+
`callback` throws an exception, the [`process` object][] `'uncaughtException'`
123+
event will be emitted.
124124

125125
In general, `queueMicrotask` is the idiomatic choice over `process.nextTick()`.
126126
`process.nextTick()` will always run before the microtask queue, and so
Collapse file

‎lib/internal/bootstrap/node.js‎

Copy file name to clipboardExpand all lines: lib/internal/bootstrap/node.js
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
_umask, _initgroups, _setegid, _seteuid,
2525
_setgid, _setuid, _setgroups,
2626
_shouldAbortOnUncaughtToggle },
27-
{ internalBinding, NativeModule }) {
27+
{ internalBinding, NativeModule },
28+
triggerFatalException) {
2829
const exceptionHandlerState = { captureFn: null };
2930
const isMainThread = internalBinding('worker').threadId === 0;
3031

@@ -538,8 +539,9 @@
538539
get: () => {
539540
process.emitWarning('queueMicrotask() is experimental.',
540541
'ExperimentalWarning');
541-
const { queueMicrotask } =
542+
const { setupQueueMicrotask } =
542543
NativeModule.require('internal/queue_microtask');
544+
const queueMicrotask = setupQueueMicrotask(triggerFatalException);
543545
Object.defineProperty(global, 'queueMicrotask', {
544546
value: queueMicrotask,
545547
writable: true,
Collapse file

‎lib/internal/queue_microtask.js‎

Copy file name to clipboardExpand all lines: lib/internal/queue_microtask.js
+27-19Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,35 @@ const { AsyncResource } = require('async_hooks');
55
const { getDefaultTriggerAsyncId } = require('internal/async_hooks');
66
const { enqueueMicrotask } = internalBinding('util');
77

8-
// declared separately for name, arrow function to prevent construction
9-
const queueMicrotask = (callback) => {
10-
if (typeof callback !== 'function') {
11-
throw new ERR_INVALID_ARG_TYPE('callback', 'function', callback);
12-
}
8+
const setupQueueMicrotask = (triggerFatalException) => {
9+
const queueMicrotask = (callback) => {
10+
if (typeof callback !== 'function') {
11+
throw new ERR_INVALID_ARG_TYPE('callback', 'function', callback);
12+
}
1313

14-
const asyncResource = new AsyncResource('Microtask', {
15-
triggerAsyncId: getDefaultTriggerAsyncId(),
16-
requireManualDestroy: true,
17-
});
14+
const asyncResource = new AsyncResource('Microtask', {
15+
triggerAsyncId: getDefaultTriggerAsyncId(),
16+
requireManualDestroy: true,
17+
});
1818

19-
enqueueMicrotask(() => {
20-
asyncResource.runInAsyncScope(() => {
21-
try {
22-
callback();
23-
} catch (e) {
24-
process.emit('error', e);
25-
}
19+
enqueueMicrotask(() => {
20+
asyncResource.runInAsyncScope(() => {
21+
try {
22+
callback();
23+
} catch (error) {
24+
// TODO(devsnek) remove this if
25+
// https://bugs.chromium.org/p/v8/issues/detail?id=8326
26+
// is resolved such that V8 triggers the fatal exception
27+
// handler for microtasks
28+
triggerFatalException(error);
29+
} finally {
30+
asyncResource.emitDestroy();
31+
}
32+
});
2633
});
27-
asyncResource.emitDestroy();
28-
});
34+
};
35+
36+
return queueMicrotask;
2937
};
3038

31-
module.exports = { queueMicrotask };
39+
module.exports = { setupQueueMicrotask };
Collapse file

‎src/node.cc‎

Copy file name to clipboardExpand all lines: src/node.cc
+18-1Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,18 @@ void FatalException(Isolate* isolate, const TryCatch& try_catch) {
14231423
}
14241424

14251425

1426+
static void FatalException(const FunctionCallbackInfo<Value>& args) {
1427+
Isolate* isolate = args.GetIsolate();
1428+
Environment* env = Environment::GetCurrent(isolate);
1429+
if (env != nullptr && env->abort_on_uncaught_exception()) {
1430+
Abort();
1431+
}
1432+
Local<Value> exception = args[0];
1433+
Local<Message> message = Exception::CreateMessage(isolate, exception);
1434+
FatalException(isolate, exception, message);
1435+
}
1436+
1437+
14261438
static void OnMessage(Local<Message> message, Local<Value> error) {
14271439
// The current version of V8 sends messages for errors only
14281440
// (thus `error` is always set).
@@ -2161,14 +2173,19 @@ void LoadEnvironment(Environment* env) {
21612173
return;
21622174
}
21632175

2176+
Local<Function> trigger_fatal_exception =
2177+
env->NewFunctionTemplate(FatalException)->GetFunction(env->context())
2178+
.ToLocalChecked();
2179+
21642180
// Bootstrap Node.js
21652181
Local<Object> bootstrapper = Object::New(env->isolate());
21662182
SetupBootstrapObject(env, bootstrapper);
21672183
Local<Value> bootstrapped_node;
21682184
Local<Value> node_bootstrapper_args[] = {
21692185
env->process_object(),
21702186
bootstrapper,
2171-
bootstrapped_loaders
2187+
bootstrapped_loaders,
2188+
trigger_fatal_exception,
21722189
};
21732190
if (!ExecuteBootstrapper(env, node_bootstrapper.ToLocalChecked(),
21742191
arraysize(node_bootstrapper_args),
Collapse file

‎test/parallel/test-queue-microtask.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-queue-microtask.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ queueMicrotask(common.mustCall(function() {
4242
}
4343

4444
const eq = [];
45-
process.on('error', (e) => {
45+
process.on('uncaughtException', (e) => {
4646
eq.push(e);
4747
});
4848

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.