-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
repl: don't use deprecated domain
module
#55204
base: main
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #55204 +/- ##
========================================
Coverage 88.41% 88.42%
========================================
Files 652 654 +2
Lines 186918 187688 +770
Branches 36072 36126 +54
========================================
+ Hits 165270 165956 +686
- Misses 14891 14963 +72
- Partials 6757 6769 +12
|
42e6441
to
fb9057d
Compare
47e132b
to
9be6f17
Compare
9be6f17
to
5f6d5ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a rough feeling that you'd need to add
a FinalizationRegistry
to clear up any instances
Why? Is unsetting the callback on |
5f6d5ec
to
dcf5e94
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
I'm convinced.
dcf5e94
to
b0d6991
Compare
This comment has been minimized.
This comment has been minimized.
I doubt we have any package on CITGM that use repl, do we? |
Got it! I've removed the label. IIRC semver-major PRs need two TSC approvals to land, would you mind reviewing? |
@nodejs/tsc add it to the agenda for visibility. |
|
||
* Uncaught exceptions only emit the [`'uncaughtException'`][] event in the | ||
standalone REPL. Adding a listener for this event in a REPL within | ||
another Node.js program results in [`ERR_INVALID_REPL_INPUT`][]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd replace this section with one that describes the new behavior and amend the changes:
YAML entry instead of dropping it (since the new behavior is definitely one that doesn't matter to some users but will have a significant negative impact on users who rely on it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think a specific section is needed, IMO there's nothing to document. it adds a listener to the process object, what negative impact does that have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@redyetidev Well, before this change, uncaughtException
listeners wouldn't have seen uncaught exceptions coming from the REPL, and now they do, right? It's not a massive change or anything, but I'd still document it somewhere. If you feel that no separate section is necessary, I'd still keep the changes:
block to document the change in behavior over time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's incorrect. Before this change, uncaughtException listeners still saw REPL exceptions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. Nevermind then!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused about this change. As far as I see it in the code, only the stand alone repl works with the uncaughtException listeners. In case more than a single REPL instance is running, it is not possible to identify the correct listeners, so none receive the errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs docs; I'd also add a test for the specific behavior that we now have when two separate REPL instances receive the same uncaught exception.
There's probably even room for a way to restore the current behavior (which is imo the clearly correct one, even if it makes use of code that's deprecated for good reasons) – we'd a) need to make the REPL take an option that tells it whether to install the global I probably misread the code and the current logic is trying to re-establish this behavior, all good.process.on('uncaughtException')
listener and b) allow users to set that flag to off, and start a REPL within a domain on their own + move errors from the domain to the REPL instance. That's not too complex, I think.
That won't happen. It's specifically set up so that an uncaught exception triggered from REPL (A) won't affect REPL (B). A test to ensure this is https://github.com/nodejs/node/pull/55204/files#diff-ca6f6e3faa6e2dc3fba74eabfc212f36fa2f84b7a17e3f73662d24b678d18f73 (although it doesn't check two REPLs, rather it verifies that an uncaught exception triggered from outside the REPL does not affect the REPL, which [testing-wise] is a similar test) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely nice work, I still think there are a few open parts though.
@@ -612,13 +626,8 @@ function REPLServer(prompt, | |||
} | |||
} catch (e) { | |||
err = e; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the assignment is AFAIK not needed anymore
}, | ||
}); | ||
|
||
let kHasSetUncaughtListener = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a constant, so I would name the variable different.
let kHasSetUncaughtListener = false; | |
let hasUncaughtExceptionListener = false; |
} | ||
}; | ||
|
||
self._onEvalError = function _onEvalError(e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great not to expose this property.
I would just pass the instance to the method so that this method is a purely internal one.
For testing purposes, we would only have to verify that nothing else is written to REPLinstance.output.write()
.
self._domain.on('error', function debugDomainError(e) { | ||
debug('domain error'); | ||
try { | ||
FunctionPrototypeApply(eval_, this, args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eval_
could be an async function provided by the user. Would it be a good idea to await that method? I am not certain if that would improve things or if it makes it more difficult
|
||
const kBufferedCommandSymbol = Symbol('bufferedCommand'); | ||
const kContextId = Symbol('contextId'); | ||
const kLoadingSymbol = Symbol('loading'); | ||
const kListeningREPLs = new SafeSet(); | ||
const kAsyncREPLMap = new SafeMap(); | ||
let kActiveREPL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let kActiveREPL; | |
let activeREPL; |
if (kActiveREPL) { | ||
kActiveREPL._onEvalError(er); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we definitely safe, that the active repl is definitely the correct one?
Let's say one repl starts an operation at time 0 and the operation needs 4 time intervals. A second repl instance start an operation at time 1 and that operation needs 2 intervals. The first instance fails after 2 intervals. Which repl instance is the error now reported upon? Do we maybe have a test for this?
|
||
* Uncaught exceptions only emit the [`'uncaughtException'`][] event in the | ||
standalone REPL. Adding a listener for this event in a REPL within | ||
another Node.js program results in [`ERR_INVALID_REPL_INPUT`][]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused about this change. As far as I see it in the code, only the stand alone repl works with the uncaughtException listeners. In case more than a single REPL instance is running, it is not possible to identify the correct listeners, so none receive the errors.
This PR refactors the REPL module by eliminating the deprecated
node:domain
module. It replaces its functionality with a modern approach using atry/catch
block andprocess
listener.Why?
The
domain
module has been deprecated for a while, and its use is discouraged. Despite this, Node.js still relies on it in a key component: the REPL. To lead by example and promote best practices, this PR updates the REPL module to use more up-to-date error-handling mechanisms, completely removing reliance on the deprecateddomain
module.Additionally, this update simplifies the REPL's code and results in a slight performance improvement—though the gains are give-or-take a few ticks and may not be noticeable.
Breaking Changes
This PR is marked as semver-majorPRs that contain breaking changes and should be released in the next major version.
because it introduces functional changes to the REPL:
options.domain
: This undocumented feature is removed (without a formal deprecation cycle, given thedomain
module itself is deprecated, and the feature was never documented nor tested).ERR_INVALID_REPL_INPUT
: This error is no longer needed, as after this change, there are no restricted inputs.This PR is also marked needs-citgmPRs that need a CITGM CI run.
in case any of the above cause breakages.
CC @nodejs/replPRs that contain breaking changes and should be released in the next major version.
CC @nodejs/tsc due to semver-major