Repository navigation
repl: useGlobal docs and code mismatch #5659
Description
Activity
I think I left a comment on your PR because of this. A documentation PR would be appreciated :-)
- addeddocIssues and PRs related to Node.js documentation.Issues and PRs related to Node.js documentation.replIssues and PRs related to the REPL subsystem.Issues and PRs related to the REPL subsystem.good first issueIssues that are suitable for first-time contributors.Issues that are suitable for first-time contributors.
on Mar 11, 2016 @cjihrig I can submit a docs PR, but is the current behavior what's desired? Currently, the default is
falseif you create a REPL programmatically, buttrueif you start a REPL from the command line. It seems odd to have two different defaults.I don't really have a strong opinion, but if we're going to break something, my choice would be to have the command line REPL default to
falsetoo. I'm not sure off the top of my head what the implications would be outside of.clear.OK, I will submit a separate PR for a change that defaults
useGlobalto
false for the command line REPLDoesn't this mean the CLI repl won't have access to any globals? i.e.
require()? That is not an acceptable breaking change, and basically invalidates how the CLI repl is designed to work...I don't think we should necessarily treat these things the same, although I think if there is no context provided to a programatic repl, it should probably use the global one.
Edit: actually, I don't think that is necessarily true... I don't think think the programatic and CLI repl should have to be the same, the purpose is not necessarily the same.
So, I've spent a while digging into how
useGlobalworks inside repl.js
and here's what I've found.When a programmer writes code like this
const start = require('repl').start; const repl = start({ prompt: 'REPL> ' });the
startfunction creates a newREPLServerobject. The default
behavior in that constructor is to set theuseGlobalvalue to
!!useGlobal, meaning that if it's not provided, then the default
value will befalse. This would be the typical case, when using
thereplmodule programmatically, and any recommended change in
this issue should not change that behavior.However, the REPL that is created by
node.jswhen a REPL is started from the
command line uses the internalcreateInternalRepl
function exported frominternal/repl.js. Here it setsuseGlobaltotrueif anoptsparameter is not provided, which is the case in the default usage. So, the command line REPL gets auseGlobalthat istrue.So what does this mean? How does it affect the behavior in practice?
In either case, access to global variables such asrequireis available
because by the time this code is executing these have
already been set.
Since theuseGlobalvariable isn't exposed anywhere else, we can limit our search torepl.js.In
REPLServer.prototype.createContext, the flag is used to determine whether or not a new context should be created, or just use the current global. This function is used by the auto-completion bits, and byREPLServer.prototype.resetContext. TheuseGlobalboolean is also used to determine
whether or not to callresetContextwhen the.clearaction is called in a REPL. And then finally, where it really matters, it's used byREPLServer'sdefaultEvalfunction.As an aside, it seems odd to me that these functions on
REPLServer.prototype
are essentially public, but not documented. It would seem better to have them
either unavailable on the prototype, or documented here.
As a bonus, I think ifcreateContextandresetContextwere privately scoped,
most of this convoluted boolean checking would go away. Because ultimately
the value ofuseGlobalonly determines one thing. It is used to determine
whether or not each statement in the REPL is evaluated
usingscript.runInThisContext(ifuseGlobalis true), orscript.runInContext
(ifuseGlobalis false). I think its usage everywhere else is simply a byproduct
of these functions being exposed.All of this is a long way of saying that I don't see this as a breaking
change, but I will agree that the complexity of this simple little boolean
value withinrepl.jsis probably a lot greater than what it should be.My personal opinion is that making the command line REPL match both the documented
behavior, and the default behavior when aREPLServeris created in code is
probably a good thing. It will not negatively impact users who are creating
REPLs in code because the default behavior there is not changing. It will
affect the REPL that is created bynodeon the command line. But it's not
entirely clear to me how other than the fact that a new context will be
created for statement evaluation instead of running in the initial context
created at node startup. But I'm a little hazy on that.Edit: To be clear, I'm not suggesting that any response to this issue should involve changing the scope of functions on
REPLServer.prototype. A change to the default CLI behavior seems pretty easy and simple, but changing those functions may be a can of worms.The change for this is really simple - a one-liner. https://github.com/nodejs/node/blob/master/lib/internal/repl.js#L25 but I've been having a little trouble writing an automated test for it. If the real purpose of the boolean flag is to determine whether
script.runInContextorscript.runInThisContextis run, it's not clear how to best test that.I know, first of all, that I'll need to have
// Flags: --expose-internalsin the test file in order to loadinternal/repl.jswhich contains the function needed for testing. But given that, is the code that is executingrunInContextrunning in the same context as both the test and the code being executed byrunInContext? And if so, by declaring avar foo;at the test level, should I expect this to be visible at the level of code being execute byrunInContext?You should be able to differentiate between
runInContext()andrunInThisContext()by the presence of a global variable. According to therunInThisContext()documentation:Running code does not have access to local scope, but does have access to the current global object.
- removedgood first issueIssues that are suitable for first-time contributors.Issues that are suitable for first-time contributors.
on Mar 14, 2016 @cjihrig ok, got it. But let's say I have a test like this https://gist.github.com/lance/6a474ad892c34eed9026. I would expect this to pass. Maybe I misunderstand what is meant by
useGlobal, because I am getting a failure here whereglobal.lunchis still returning'tacos'. Have I discovered another bug? Or am I just missing something obvious.When you set
useGlobaltofalse, it still copies things from the global context into the new context inREPLServer.prototype.createContext(). In your example, try movingglobal.lunch = 'tacos';into thecreateInternalRepl()callback. That should demonstrate the different behavior ofuseGlobal.1 remaining item
@cjihrig thanks - I've got a working test now - realized my oversight. I will submit a PR this afternoon.
I found this change after an alias I had set stopped working. Prior to the update, I could set:
alias='node -e repl.repl.ignoreUndefined=true -i'
in bashrc and run the default nodejs repl that ignored undefined. Post update I get a ReferenceError.It's probably not a big enough issue to address, but it was the only way I could figure out how to modify the default repl. Running a script that starts a new repl instance doesn't help because the new repl doesn't have access to the default repl's history.
@cydhaselton this was just reverted in #7795. A documentation PR might be appropriate just to note that the CLI REPL defaults to
useGlobal: true.Thanks @cjihrig. Was there a release that incorporated the reversion?
Not yet. It was just reverted an hour ago :-)
Reacted by Cyd HaseltonApologies…reviewing from tablet. Missed the timestamps :-/
Related question: is there a quick way to tell if a release contains a reversion?
The quickest way I can think of would be checking the changelog or release blog post.
I did…the latest only has changes and commits. Do they usually show reversions/fixes, if any?
Yes. They should show all commits, including reverts. It looks like 2cc01da didn't make it into the v6.3.1 release, which was already in progress. It should be in the next release though.
- added a commit that references this issue
on Jul 27, 2026
The API documentation for REPL says,
"
useGlobal- if set totrue, then the repl will use the global object, instead of running scripts in a separate context. Defaults tofalse."This is only true if a REPL is created programmatically. The REPL that is created by simply typing
nodeon the command line defaultsuseGlobaltotrue.This is because the internal
createReplfunction, used bynode.jshere, defaults this value totrue. https://github.com/nodejs/node/blob/master/lib/internal/repl.js#L25This can be verified by simply firing up a node REPL and typing
.clear. You should see on the REPL command line, this text, "Clearing context....", but you don't.