11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciconst assert = require('assert'); 51cb0ef41Sopenharmony_ciconst fs = require('fs'); 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci// The goal of this test is to make sure that: 81cb0ef41Sopenharmony_ci// 91cb0ef41Sopenharmony_ci// - Even if --abort_on_uncaught_exception is passed on the command line, 101cb0ef41Sopenharmony_ci// setting up a top-level domain error handler and throwing an error 111cb0ef41Sopenharmony_ci// within this domain does *not* make the process abort. The process exits 121cb0ef41Sopenharmony_ci// gracefully. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// - When passing --abort_on_uncaught_exception on the command line and 151cb0ef41Sopenharmony_ci// setting up a top-level domain error handler, an error thrown 161cb0ef41Sopenharmony_ci// within this domain's error handler *does* make the process abort. 171cb0ef41Sopenharmony_ci// 181cb0ef41Sopenharmony_ci// - When *not* passing --abort_on_uncaught_exception on the command line and 191cb0ef41Sopenharmony_ci// setting up a top-level domain error handler, an error thrown within this 201cb0ef41Sopenharmony_ci// domain's error handler does *not* make the process abort, but makes it exit 211cb0ef41Sopenharmony_ci// with the proper failure exit code. 221cb0ef41Sopenharmony_ci// 231cb0ef41Sopenharmony_ci// - When throwing an error within the top-level domain's error handler 241cb0ef41Sopenharmony_ci// within a try/catch block, the process should exit gracefully, whether or 251cb0ef41Sopenharmony_ci// not --abort_on_uncaught_exception is passed on the command line. 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciconst domainErrHandlerExMessage = 'exception from domain error handler'; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ciif (process.argv[2] === 'child') { 301cb0ef41Sopenharmony_ci const domain = require('domain'); 311cb0ef41Sopenharmony_ci const d = domain.create(); 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci process.on('uncaughtException', function onUncaughtException() { 341cb0ef41Sopenharmony_ci // The process' uncaughtException event must not be emitted when 351cb0ef41Sopenharmony_ci // an error handler is setup on the top-level domain. 361cb0ef41Sopenharmony_ci // Exiting with exit code of 42 here so that it would assert when 371cb0ef41Sopenharmony_ci // the parent checks the child exit code. 381cb0ef41Sopenharmony_ci process.exit(42); 391cb0ef41Sopenharmony_ci }); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci d.on('error', function(err) { 421cb0ef41Sopenharmony_ci // Swallowing the error on purpose if 'throwInDomainErrHandler' is not 431cb0ef41Sopenharmony_ci // set 441cb0ef41Sopenharmony_ci if (process.argv.includes('throwInDomainErrHandler')) { 451cb0ef41Sopenharmony_ci // If useTryCatch is set, wrap the throw in a try/catch block. 461cb0ef41Sopenharmony_ci // This is to make sure that a caught exception does not trigger 471cb0ef41Sopenharmony_ci // an abort. 481cb0ef41Sopenharmony_ci if (process.argv.includes('useTryCatch')) { 491cb0ef41Sopenharmony_ci try { 501cb0ef41Sopenharmony_ci throw new Error(domainErrHandlerExMessage); 511cb0ef41Sopenharmony_ci } catch { 521cb0ef41Sopenharmony_ci // Continue regardless of error. 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci } else { 551cb0ef41Sopenharmony_ci throw new Error(domainErrHandlerExMessage); 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci }); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci d.run(function doStuff() { 611cb0ef41Sopenharmony_ci // Throwing from within different types of callbacks as each of them 621cb0ef41Sopenharmony_ci // handles domains differently 631cb0ef41Sopenharmony_ci process.nextTick(function() { 641cb0ef41Sopenharmony_ci throw new Error('Error from nextTick callback'); 651cb0ef41Sopenharmony_ci }); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci fs.exists('/non/existing/file', function onExists(exists) { 681cb0ef41Sopenharmony_ci throw new Error('Error from fs.exists callback'); 691cb0ef41Sopenharmony_ci }); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci setImmediate(function onSetImmediate() { 721cb0ef41Sopenharmony_ci throw new Error('Error from setImmediate callback'); 731cb0ef41Sopenharmony_ci }); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci setTimeout(function onTimeout() { 761cb0ef41Sopenharmony_ci throw new Error('Error from setTimeout callback'); 771cb0ef41Sopenharmony_ci }, 0); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci throw new Error('Error from domain.run callback'); 801cb0ef41Sopenharmony_ci }); 811cb0ef41Sopenharmony_ci} else { 821cb0ef41Sopenharmony_ci const exec = require('child_process').exec; 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci function testDomainExceptionHandling(cmdLineOption, options) { 851cb0ef41Sopenharmony_ci if (typeof cmdLineOption === 'object') { 861cb0ef41Sopenharmony_ci options = cmdLineOption; 871cb0ef41Sopenharmony_ci cmdLineOption = undefined; 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci let throwInDomainErrHandlerOpt; 911cb0ef41Sopenharmony_ci if (options.throwInDomainErrHandler) 921cb0ef41Sopenharmony_ci throwInDomainErrHandlerOpt = 'throwInDomainErrHandler'; 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci let cmdToExec = ''; 951cb0ef41Sopenharmony_ci if (!common.isWindows) { 961cb0ef41Sopenharmony_ci // Do not create core files, as it can take a lot of disk space on 971cb0ef41Sopenharmony_ci // continuous testing and developers' machines 981cb0ef41Sopenharmony_ci cmdToExec += 'ulimit -c 0 && '; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci let useTryCatchOpt; 1021cb0ef41Sopenharmony_ci if (options.useTryCatch) 1031cb0ef41Sopenharmony_ci useTryCatchOpt = 'useTryCatch'; 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci cmdToExec += `"${process.argv[0]}" ${cmdLineOption ? cmdLineOption : ''} "${ 1061cb0ef41Sopenharmony_ci process.argv[1]}" child ${throwInDomainErrHandlerOpt} ${useTryCatchOpt}`; 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci const child = exec(cmdToExec); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci if (child) { 1111cb0ef41Sopenharmony_ci child.on('exit', function onChildExited(exitCode, signal) { 1121cb0ef41Sopenharmony_ci // When throwing errors from the top-level domain error handler 1131cb0ef41Sopenharmony_ci // outside of a try/catch block, the process should not exit gracefully 1141cb0ef41Sopenharmony_ci if (!options.useTryCatch && options.throwInDomainErrHandler) { 1151cb0ef41Sopenharmony_ci if (cmdLineOption === '--abort_on_uncaught_exception') { 1161cb0ef41Sopenharmony_ci assert(common.nodeProcessAborted(exitCode, signal), 1171cb0ef41Sopenharmony_ci 'process should have aborted, but did not'); 1181cb0ef41Sopenharmony_ci } else { 1191cb0ef41Sopenharmony_ci // By default, uncaught exceptions make node exit with an exit 1201cb0ef41Sopenharmony_ci // code of 7. 1211cb0ef41Sopenharmony_ci assert.strictEqual(exitCode, 7); 1221cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci } else { 1251cb0ef41Sopenharmony_ci // If the top-level domain's error handler does not throw, 1261cb0ef41Sopenharmony_ci // the process must exit gracefully, whether or not 1271cb0ef41Sopenharmony_ci // --abort_on_uncaught_exception was passed on the command line 1281cb0ef41Sopenharmony_ci assert.strictEqual(exitCode, 0); 1291cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci }); 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci testDomainExceptionHandling('--abort_on_uncaught_exception', { 1361cb0ef41Sopenharmony_ci throwInDomainErrHandler: false, 1371cb0ef41Sopenharmony_ci useTryCatch: false 1381cb0ef41Sopenharmony_ci }); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci testDomainExceptionHandling('--abort_on_uncaught_exception', { 1411cb0ef41Sopenharmony_ci throwInDomainErrHandler: false, 1421cb0ef41Sopenharmony_ci useTryCatch: true 1431cb0ef41Sopenharmony_ci }); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci testDomainExceptionHandling('--abort_on_uncaught_exception', { 1461cb0ef41Sopenharmony_ci throwInDomainErrHandler: true, 1471cb0ef41Sopenharmony_ci useTryCatch: false 1481cb0ef41Sopenharmony_ci }); 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci testDomainExceptionHandling('--abort_on_uncaught_exception', { 1511cb0ef41Sopenharmony_ci throwInDomainErrHandler: true, 1521cb0ef41Sopenharmony_ci useTryCatch: true 1531cb0ef41Sopenharmony_ci }); 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci testDomainExceptionHandling({ 1561cb0ef41Sopenharmony_ci throwInDomainErrHandler: false 1571cb0ef41Sopenharmony_ci }); 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci testDomainExceptionHandling({ 1601cb0ef41Sopenharmony_ci throwInDomainErrHandler: false, 1611cb0ef41Sopenharmony_ci useTryCatch: false 1621cb0ef41Sopenharmony_ci }); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci testDomainExceptionHandling({ 1651cb0ef41Sopenharmony_ci throwInDomainErrHandler: true, 1661cb0ef41Sopenharmony_ci useTryCatch: true 1671cb0ef41Sopenharmony_ci }); 1681cb0ef41Sopenharmony_ci} 169