| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7be4a39 commit 1c4d7eb
12 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,16 +18,30 @@ | |||
| 18 | 18 | ||
| 19 | 19 | const { internalBinding, NativeModule } = loaderExports; | |
| 20 | 20 | ||
| 21 | - const exceptionHandlerState = { captureFn: null }; | ||
| 22 | 21 | let getOptionValue; | |
| 23 | 22 | ||
| 24 | 23 | function startup() { | |
| 25 | 24 | setupTraceCategoryState(); | |
| 26 | 25 | ||
| 27 | 26 | setupProcessObject(); | |
| 28 | 27 | ||
| 29 | - // Do this good and early, since it handles errors. | ||
| 30 | - setupProcessFatal(); | ||
| 28 | + // TODO(joyeecheung): this does not have to done so early, any fatal errors | ||
| 29 | + // thrown before user code execution should simply crash the process | ||
| 30 | + // and we do not care about any clean up at that point. We don't care | ||
| 31 | + // about emitting any events if the process crash upon bootstrap either. | ||
| 32 | + { | ||
| 33 | + const { | ||
| 34 | + fatalException, | ||
| 35 | + setUncaughtExceptionCaptureCallback, | ||
| 36 | + hasUncaughtExceptionCaptureCallback | ||
| 37 | + } = NativeModule.require('internal/process/execution'); | ||
| 38 | + | ||
| 39 | + process._fatalException = fatalException; | ||
| 40 | + process.setUncaughtExceptionCaptureCallback = | ||
| 41 | + setUncaughtExceptionCaptureCallback; | ||
| 42 | + process.hasUncaughtExceptionCaptureCallback = | ||
| 43 | + hasUncaughtExceptionCaptureCallback; | ||
| 44 | + } | ||
| 31 | 45 | ||
| 32 | 46 | setupGlobalVariables(); | |
| 33 | 47 | ||
@@ -83,20 +97,14 @@ function startup() { | |||
| 83 | 97 | process.reallyExit = rawMethods.reallyExit; | |
| 84 | 98 | process._kill = rawMethods._kill; | |
| 85 | 99 | ||
| 86 | - const wrapped = perThreadSetup.wrapProcessMethods( | ||
| 87 | - rawMethods, exceptionHandlerState | ||
| 88 | - ); | ||
| 100 | + const wrapped = perThreadSetup.wrapProcessMethods(rawMethods); | ||
| 89 | 101 | process._rawDebug = wrapped._rawDebug; | |
| 90 | 102 | process.hrtime = wrapped.hrtime; | |
| 91 | 103 | process.hrtime.bigint = wrapped.hrtimeBigInt; | |
| 92 | 104 | process.cpuUsage = wrapped.cpuUsage; | |
| 93 | 105 | process.memoryUsage = wrapped.memoryUsage; | |
| 94 | 106 | process.kill = wrapped.kill; | |
| 95 | 107 | process.exit = wrapped.exit; | |
| 96 | - process.setUncaughtExceptionCaptureCallback = | ||
| 97 | - wrapped.setUncaughtExceptionCaptureCallback; | ||
| 98 | - process.hasUncaughtExceptionCaptureCallback = | ||
| 99 | - wrapped.hasUncaughtExceptionCaptureCallback; | ||
| 100 | 108 | } | |
| 101 | 109 | ||
| 102 | 110 | NativeModule.require('internal/process/warning').setup(); | |
@@ -311,7 +319,7 @@ function startExecution() { | |||
| 311 | 319 | // This means we are in a Worker context, and any script execution | |
| 312 | 320 | // will be directed by the worker module. | |
| 313 | 321 | if (internalBinding('worker').getEnvMessagePort() !== undefined) { | |
| 314 | - NativeModule.require('internal/worker').setupChild(evalScript); | ||
| 322 | + NativeModule.require('internal/worker').setupChild(); | ||
| 315 | 323 | return; | |
| 316 | 324 | } | |
| 317 | 325 | ||
@@ -382,7 +390,9 @@ function executeUserCode() { | |||
| 382 | 390 | addBuiltinLibsToObject | |
| 383 | 391 | } = NativeModule.require('internal/modules/cjs/helpers'); | |
| 384 | 392 | addBuiltinLibsToObject(global); | |
| 385 | - evalScript('[eval]', wrapForBreakOnFirstLine(getOptionValue('--eval'))); | ||
| 393 | + const source = getOptionValue('--eval'); | ||
| 394 | + const { evalScript } = NativeModule.require('internal/process/execution'); | ||
| 395 | + evalScript('[eval]', source, process._breakFirstLine); | ||
| 386 | 396 | return; | |
| 387 | 397 | } | |
| 388 | 398 | ||
@@ -436,7 +446,8 @@ function executeUserCode() { | |||
| 436 | 446 | ||
| 437 | 447 | // User passed '-e' or '--eval' along with `-i` or `--interactive` | |
| 438 | 448 | if (process._eval != null) { | |
| 439 | - evalScript('[eval]', wrapForBreakOnFirstLine(process._eval)); | ||
| 449 | + const { evalScript } = NativeModule.require('internal/process/execution'); | ||
| 450 | + evalScript('[eval]', process._eval, process._breakFirstLine); | ||
| 440 | 451 | } | |
| 441 | 452 | return; | |
| 442 | 453 | } | |
@@ -458,7 +469,8 @@ function readAndExecuteStdin() { | |||
| 458 | 469 | checkScriptSyntax(code, '[stdin]'); | |
| 459 | 470 | } else { | |
| 460 | 471 | process._eval = code; | |
| 461 | - evalScript('[stdin]', wrapForBreakOnFirstLine(process._eval)); | ||
| 472 | + const { evalScript } = NativeModule.require('internal/process/execution'); | ||
| 473 | + evalScript('[stdin]', process._eval, process._breakFirstLine); | ||
| 462 | 474 | } | |
| 463 | 475 | }); | |
| 464 | 476 | } | |
@@ -654,93 +666,6 @@ function setupDOMException() { | |||
| 654 | 666 | ||
| 655 | 667 | function noop() {} | |
| 656 | 668 | ||
| 657 | - function setupProcessFatal() { | ||
| 658 | - const { | ||
| 659 | - executionAsyncId, | ||
| 660 | - clearDefaultTriggerAsyncId, | ||
| 661 | - clearAsyncIdStack, | ||
| 662 | - hasAsyncIdStack, | ||
| 663 | - afterHooksExist, | ||
| 664 | - emitAfter | ||
| 665 | - } = NativeModule.require('internal/async_hooks'); | ||
| 666 | - | ||
| 667 | - process._fatalException = (er) => { | ||
| 668 | - // It's possible that defaultTriggerAsyncId was set for a constructor | ||
| 669 | - // call that threw and was never cleared. So clear it now. | ||
| 670 | - clearDefaultTriggerAsyncId(); | ||
| 671 | - | ||
| 672 | - if (exceptionHandlerState.captureFn !== null) { | ||
| 673 | - exceptionHandlerState.captureFn(er); | ||
| 674 | - } else if (!process.emit('uncaughtException', er)) { | ||
| 675 | - // If someone handled it, then great. otherwise, die in C++ land | ||
| 676 | - // since that means that we'll exit the process, emit the 'exit' event. | ||
| 677 | - try { | ||
| 678 | - if (!process._exiting) { | ||
| 679 | - process._exiting = true; | ||
| 680 | - process.exitCode = 1; | ||
| 681 | - process.emit('exit', 1); | ||
| 682 | - } | ||
| 683 | - } catch { | ||
| 684 | - // Nothing to be done about it at this point. | ||
| 685 | - } | ||
| 686 | - try { | ||
| 687 | - const { kExpandStackSymbol } = NativeModule.require('internal/util'); | ||
| 688 | - if (typeof er[kExpandStackSymbol] === 'function') | ||
| 689 | - er[kExpandStackSymbol](); | ||
| 690 | - } catch { | ||
| 691 | - // Nothing to be done about it at this point. | ||
| 692 | - } | ||
| 693 | - return false; | ||
| 694 | - } | ||
| 695 | - | ||
| 696 | - // If we handled an error, then make sure any ticks get processed | ||
| 697 | - // by ensuring that the next Immediate cycle isn't empty. | ||
| 698 | - NativeModule.require('timers').setImmediate(noop); | ||
| 699 | - | ||
| 700 | - // Emit the after() hooks now that the exception has been handled. | ||
| 701 | - if (afterHooksExist()) { | ||
| 702 | - do { | ||
| 703 | - emitAfter(executionAsyncId()); | ||
| 704 | - } while (hasAsyncIdStack()); | ||
| 705 | - // Or completely empty the id stack. | ||
| 706 | - } else { | ||
| 707 | - clearAsyncIdStack(); | ||
| 708 | - } | ||
| 709 | - | ||
| 710 | - return true; | ||
| 711 | - }; | ||
| 712 | - } | ||
| 713 | - | ||
| 714 | - function wrapForBreakOnFirstLine(source) { | ||
| 715 | - if (!process._breakFirstLine) | ||
| 716 | - return source; | ||
| 717 | - const fn = `function() {\n\n${source};\n\n}`; | ||
| 718 | - return `process.binding('inspector').callAndPauseOnStart(${fn}, {})`; | ||
| 719 | - } | ||
| 720 | - | ||
| 721 | - function evalScript(name, body) { | ||
| 722 | - const CJSModule = NativeModule.require('internal/modules/cjs/loader'); | ||
| 723 | - const path = NativeModule.require('path'); | ||
| 724 | - const { tryGetCwd } = NativeModule.require('internal/util'); | ||
| 725 | - const cwd = tryGetCwd(path); | ||
| 726 | - | ||
| 727 | - const module = new CJSModule(name); | ||
| 728 | - module.filename = path.join(cwd, name); | ||
| 729 | - module.paths = CJSModule._nodeModulePaths(cwd); | ||
| 730 | - const script = `global.__filename = ${JSON.stringify(name)};\n` + | ||
| 731 | - 'global.exports = exports;\n' + | ||
| 732 | - 'global.module = module;\n' + | ||
| 733 | - 'global.__dirname = __dirname;\n' + | ||
| 734 | - 'global.require = require;\n' + | ||
| 735 | - 'return require("vm").runInThisContext(' + | ||
| 736 | - `${JSON.stringify(body)}, { filename: ` + | ||
| 737 | - `${JSON.stringify(name)}, displayErrors: true });\n`; | ||
| 738 | - const result = module._compile(script, `${name}-wrapper`); | ||
| 739 | - if (getOptionValue('--print')) console.log(result); | ||
| 740 | - // Handle any nextTicks added in the first tick of the program. | ||
| 741 | - process._tickCallback(); | ||
| 742 | - } | ||
| 743 | - | ||
| 744 | 669 | function checkScriptSyntax(source, filename) { | |
| 745 | 670 | const CJSModule = NativeModule.require('internal/modules/cjs/loader'); | |
| 746 | 671 | const vm = NativeModule.require('vm'); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,15 +1,14 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | - const path = require('path'); | ||
| 4 | 3 | const CJSModule = require('internal/modules/cjs/loader'); | |
| 5 | 4 | const { makeRequireFunction } = require('internal/modules/cjs/helpers'); | |
| 6 | - const { tryGetCwd } = require('internal/util'); | ||
| 5 | + const { tryGetCwd } = require('internal/process/execution'); | ||
| 7 | 6 | const { addCommandLineAPI, consoleCall } = internalBinding('inspector'); | |
| 8 | 7 | ||
| 9 | 8 | // Wrap a console implemented by Node.js with features from the VM inspector | |
| 10 | 9 | function addInspectorApis(consoleFromNode, consoleFromVM) { | |
| 11 | 10 | // Setup inspector command line API. | |
| 12 | - const cwd = tryGetCwd(path); | ||
| 11 | + const cwd = tryGetCwd(); | ||
| 13 | 12 | const consoleAPIModule = new CJSModule('<inspector console>'); | |
| 14 | 13 | consoleAPIModule.paths = | |
| 15 | 14 | CJSModule._nodeModulePaths(cwd).concat(CJSModule.globalPaths); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,149 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const path = require('path'); | ||
| 4 | + | ||
| 5 | + const { | ||
| 6 | + codes: { | ||
| 7 | + ERR_INVALID_ARG_TYPE, | ||
| 8 | + ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET | ||
| 9 | + } | ||
| 10 | + } = require('internal/errors'); | ||
| 11 | + | ||
| 12 | + const { | ||
| 13 | + executionAsyncId, | ||
| 14 | + clearDefaultTriggerAsyncId, | ||
| 15 | + clearAsyncIdStack, | ||
| 16 | + hasAsyncIdStack, | ||
| 17 | + afterHooksExist, | ||
| 18 | + emitAfter | ||
| 19 | + } = require('internal/async_hooks'); | ||
| 20 | + | ||
| 21 | + // shouldAbortOnUncaughtToggle is a typed array for faster | ||
| 22 | + // communication with JS. | ||
| 23 | + const { shouldAbortOnUncaughtToggle } = internalBinding('util'); | ||
| 24 | + | ||
| 25 | + function tryGetCwd() { | ||
| 26 | + try { | ||
| 27 | + return process.cwd(); | ||
| 28 | + } catch { | ||
| 29 | + // getcwd(3) can fail if the current working directory has been deleted. | ||
| 30 | + // Fall back to the directory name of the (absolute) executable path. | ||
| 31 | + // It's not really correct but what are the alternatives? | ||
| 32 | + return path.dirname(process.execPath); | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + function evalScript(name, body, breakFristLine) { | ||
| 37 | + const CJSModule = require('internal/modules/cjs/loader'); | ||
| 38 | + if (breakFristLine) { | ||
| 39 | + const fn = `function() {\n\n${body};\n\n}`; | ||
| 40 | + body = `process.binding('inspector').callAndPauseOnStart(${fn}, {})`; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + const cwd = tryGetCwd(); | ||
| 44 | + | ||
| 45 | + const module = new CJSModule(name); | ||
| 46 | + module.filename = path.join(cwd, name); | ||
| 47 | + module.paths = CJSModule._nodeModulePaths(cwd); | ||
| 48 | + const script = `global.__filename = ${JSON.stringify(name)};\n` + | ||
| 49 | + 'global.exports = exports;\n' + | ||
| 50 | + 'global.module = module;\n' + | ||
| 51 | + 'global.__dirname = __dirname;\n' + | ||
| 52 | + 'global.require = require;\n' + | ||
| 53 | + 'return require("vm").runInThisContext(' + | ||
| 54 | + `${JSON.stringify(body)}, { filename: ` + | ||
| 55 | + `${JSON.stringify(name)}, displayErrors: true });\n`; | ||
| 56 | + const result = module._compile(script, `${name}-wrapper`); | ||
| 57 | + if (require('internal/options').getOptionValue('--print')) { | ||
| 58 | + console.log(result); | ||
| 59 | + } | ||
| 60 | + // Handle any nextTicks added in the first tick of the program. | ||
| 61 | + process._tickCallback(); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + const exceptionHandlerState = { captureFn: null }; | ||
| 65 | + | ||
| 66 | + function setUncaughtExceptionCaptureCallback(fn) { | ||
| 67 | + if (fn === null) { | ||
| 68 | + exceptionHandlerState.captureFn = fn; | ||
| 69 | + shouldAbortOnUncaughtToggle[0] = 1; | ||
| 70 | + return; | ||
| 71 | + } | ||
| 72 | + if (typeof fn !== 'function') { | ||
| 73 | + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'null'], fn); | ||
| 74 | + } | ||
| 75 | + if (exceptionHandlerState.captureFn !== null) { | ||
| 76 | + throw new ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET(); | ||
| 77 | + } | ||
| 78 | + exceptionHandlerState.captureFn = fn; | ||
| 79 | + shouldAbortOnUncaughtToggle[0] = 0; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + function hasUncaughtExceptionCaptureCallback() { | ||
| 83 | + return exceptionHandlerState.captureFn !== null; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + function noop() {} | ||
| 87 | + | ||
| 88 | + // XXX(joyeecheung): for some reason this cannot be defined at the top-level | ||
| 89 | + // and exported to be written to process._fatalException, it has to be | ||
| 90 | + // returned as an *anonymous function* wrapped inside a factory function, | ||
| 91 | + // otherwise it breaks the test-timers.setInterval async hooks test - | ||
| 92 | + // this may indicate that node::FatalException should fix up the callback scope | ||
| 93 | + // before calling into process._fatalException, or this function should | ||
| 94 | + // take extra care of the async hooks before it schedules a setImmediate. | ||
| 95 | + function createFatalException() { | ||
| 96 | + return (er) => { | ||
| 97 | + // It's possible that defaultTriggerAsyncId was set for a constructor | ||
| 98 | + // call that threw and was never cleared. So clear it now. | ||
| 99 | + clearDefaultTriggerAsyncId(); | ||
| 100 | + | ||
| 101 | + if (exceptionHandlerState.captureFn !== null) { | ||
| 102 | + exceptionHandlerState.captureFn(er); | ||
| 103 | + } else if (!process.emit('uncaughtException', er)) { | ||
| 104 | + // If someone handled it, then great. otherwise, die in C++ land | ||
| 105 | + // since that means that we'll exit the process, emit the 'exit' event. | ||
| 106 | + try { | ||
| 107 | + if (!process._exiting) { | ||
| 108 | + process._exiting = true; | ||
| 109 | + process.exitCode = 1; | ||
| 110 | + process.emit('exit', 1); | ||
| 111 | + } | ||
| 112 | + } catch { | ||
| 113 | + // Nothing to be done about it at this point. | ||
| 114 | + } | ||
| 115 | + try { | ||
| 116 | + const { kExpandStackSymbol } = require('internal/util'); | ||
| 117 | + if (typeof er[kExpandStackSymbol] === 'function') | ||
| 118 | + er[kExpandStackSymbol](); | ||
| 119 | + } catch { | ||
| 120 | + // Nothing to be done about it at this point. | ||
| 121 | + } | ||
| 122 | + return false; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + // If we handled an error, then make sure any ticks get processed | ||
| 126 | + // by ensuring that the next Immediate cycle isn't empty. | ||
| 127 | + require('timers').setImmediate(noop); | ||
| 128 | + | ||
| 129 | + // Emit the after() hooks now that the exception has been handled. | ||
| 130 | + if (afterHooksExist()) { | ||
| 131 | + do { | ||
| 132 | + emitAfter(executionAsyncId()); | ||
| 133 | + } while (hasAsyncIdStack()); | ||
| 134 | + // Or completely empty the id stack. | ||
| 135 | + } else { | ||
| 136 | + clearAsyncIdStack(); | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + return true; | ||
| 140 | + }; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + module.exports = { | ||
| 144 | + tryGetCwd, | ||
| 145 | + evalScript, | ||
| 146 | + fatalException: createFatalException(), | ||
| 147 | + setUncaughtExceptionCaptureCallback, | ||
| 148 | + hasUncaughtExceptionCaptureCallback | ||
| 149 | + }; | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments