Revert "repl: always check for NODE_REPL_MODE environment variable"

This reverts commit b831b081c499a614c1ee3f0272c9de1783395402.

This presumably unbreaks the ASAN github action build.

Example failure:

    2020-06-25T19:59:15.1448178Z === release test-repl-envvars ===
    2020-06-25T19:59:15.1448872Z Path: parallel/test-repl-envvars
    2020-06-25T19:59:15.1449449Z --- stderr ---
    2020-06-25T19:59:15.1449835Z assert.js:103
    2020-06-25T19:59:15.1450194Z   throw new AssertionError(obj);
    2020-06-25T19:59:15.1450524Z   ^
    2020-06-25T19:59:15.1450817Z
    2020-06-25T19:59:15.1451431Z AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
    2020-06-25T19:59:15.1452000Z + actual - expected
    2020-06-25T19:59:15.1452298Z
    2020-06-25T19:59:15.1452634Z   {
    2020-06-25T19:59:15.1452978Z     terminal: true,
    2020-06-25T19:59:15.1453321Z +   useColors: false
    2020-06-25T19:59:15.1453861Z -   useColors: true
    2020-06-25T19:59:15.1454225Z   }
    2020-06-25T19:59:15.1454841Z     at /home/runner/work/node/node/test/parallel/test-repl-envvars.js:55:12
    2020-06-25T19:59:15.1455246Z     at internal/repl.js:33:5

PR-URL: https://github.com/nodejs/node/pull/34058
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Anna Henningsen 2020-06-26 02:17:00 +02:00 committed by Rich Trott
parent 82f13fa803
commit 072feec1b0
12 changed files with 109 additions and 73 deletions

View File

@ -555,10 +555,6 @@ A list of the names of all Node.js modules, e.g., `'http'`.
<!-- YAML <!-- YAML
added: v0.1.91 added: v0.1.91
changes: changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/33461
description: The `NODE_REPL_MODE` environment variable now accounts for
all repl instances.
- version: - version:
- v13.4.0 - v13.4.0
- v12.17.0 - v12.17.0

View File

@ -35,7 +35,21 @@ if (process.env.NODE_REPL_EXTERNAL_MODULE) {
console.log(`Welcome to Node.js ${process.version}.\n` + console.log(`Welcome to Node.js ${process.version}.\n` +
'Type ".help" for more information.'); 'Type ".help" for more information.');
require('internal/repl').createInternalRepl(); const cliRepl = require('internal/repl');
cliRepl.createInternalRepl(process.env, (err, repl) => {
if (err) {
throw err;
}
repl.on('exit', () => {
if (repl._flushing) {
repl.pause();
return repl.once('flushHistory', () => {
process.exit();
});
}
process.exit();
});
});
// If user passed '-e' or '--eval' along with `-i` or `--interactive`, // If user passed '-e' or '--eval' along with `-i` or `--interactive`,
// evaluate the code in the current context. // evaluate the code in the current context.

View File

@ -3,21 +3,44 @@
const { const {
Number, Number,
NumberIsNaN, NumberIsNaN,
ObjectCreate,
} = primordials; } = primordials;
const REPL = require('repl'); const REPL = require('repl');
const { kStandaloneREPL } = require('internal/repl/utils'); const { kStandaloneREPL } = require('internal/repl/utils');
function createInternalRepl(opts = {}, callback = () => {}) { module.exports = ObjectCreate(REPL);
module.exports.createInternalRepl = createRepl;
function createRepl(env, opts, cb) {
if (typeof opts === 'function') {
cb = opts;
opts = null;
}
opts = { opts = {
[kStandaloneREPL]: true, [kStandaloneREPL]: true,
ignoreUndefined: false,
useGlobal: true, useGlobal: true,
breakEvalOnSigint: true, breakEvalOnSigint: true,
...opts, ...opts
terminal: parseInt(process.env.NODE_NO_READLINE) ? false : opts.terminal,
}; };
const historySize = Number(process.env.NODE_REPL_HISTORY_SIZE); if (parseInt(env.NODE_NO_READLINE)) {
opts.terminal = false;
}
if (env.NODE_REPL_MODE) {
opts.replMode = {
'strict': REPL.REPL_MODE_STRICT,
'sloppy': REPL.REPL_MODE_SLOPPY
}[env.NODE_REPL_MODE.toLowerCase().trim()];
}
if (opts.replMode === undefined) {
opts.replMode = REPL.REPL_MODE_SLOPPY;
}
const historySize = Number(env.NODE_REPL_HISTORY_SIZE);
if (!NumberIsNaN(historySize) && historySize > 0) { if (!NumberIsNaN(historySize) && historySize > 0) {
opts.historySize = historySize; opts.historySize = historySize;
} else { } else {
@ -25,13 +48,6 @@ function createInternalRepl(opts = {}, callback = () => {}) {
} }
const repl = REPL.start(opts); const repl = REPL.start(opts);
const historyPath = repl.terminal ? process.env.NODE_REPL_HISTORY : ''; const term = 'terminal' in opts ? opts.terminal : process.stdout.isTTY;
repl.setupHistory(historyPath, (err, repl) => { repl.setupHistory(term ? env.NODE_REPL_HISTORY : '', cb);
if (err) {
throw err;
} }
callback(repl);
});
}
module.exports = { createInternalRepl };

View File

@ -115,7 +115,6 @@ const {
setupPreview, setupPreview,
setupReverseSearch, setupReverseSearch,
} = require('internal/repl/utils'); } = require('internal/repl/utils');
const { hasColors } = require('internal/tty');
const { const {
getOwnNonIndexProperties, getOwnNonIndexProperties,
propertyFilter: { propertyFilter: {
@ -214,8 +213,8 @@ function REPLServer(prompt,
// If possible, check if stdout supports colors or not. // If possible, check if stdout supports colors or not.
if (options.output.hasColors) { if (options.output.hasColors) {
options.useColors = options.output.hasColors(); options.useColors = options.output.hasColors();
} else { } else if (process.env.NODE_DISABLE_COLORS === undefined) {
options.useColors = hasColors(); options.useColors = true;
} }
} }
@ -260,6 +259,7 @@ function REPLServer(prompt,
this._domain = options.domain || domain.create(); this._domain = options.domain || domain.create();
this.useGlobal = !!useGlobal; this.useGlobal = !!useGlobal;
this.ignoreUndefined = !!ignoreUndefined; this.ignoreUndefined = !!ignoreUndefined;
this.replMode = replMode || module.exports.REPL_MODE_SLOPPY;
this.underscoreAssigned = false; this.underscoreAssigned = false;
this.last = undefined; this.last = undefined;
this.underscoreErrAssigned = false; this.underscoreErrAssigned = false;
@ -269,11 +269,6 @@ function REPLServer(prompt,
// Context id for use with the inspector protocol. // Context id for use with the inspector protocol.
this[kContextId] = undefined; this[kContextId] = undefined;
this.replMode = replMode ||
(/^\s*strict\s*$/i.test(process.env.NODE_REPL_MODE) ?
module.exports.REPL_MODE_STRICT :
module.exports.REPL_MODE_SLOPPY);
if (this.breakEvalOnSigint && eval_) { if (this.breakEvalOnSigint && eval_) {
// Allowing this would not reflect user expectations. // Allowing this would not reflect user expectations.
// breakEvalOnSigint affects only the behavior of the default eval(). // breakEvalOnSigint affects only the behavior of the default eval().

View File

@ -20,7 +20,6 @@ inout._write = function(s, _, cb) {
const repl = new REPLServer({ input: inout, output: inout, useColors: true }); const repl = new REPLServer({ input: inout, output: inout, useColors: true });
inout.isTTY = true; inout.isTTY = true;
inout.hasColors = () => true;
const repl2 = new REPLServer({ input: inout, output: inout }); const repl2 = new REPLServer({ input: inout, output: inout });
process.on('exit', function() { process.on('exit', function() {

View File

@ -6,11 +6,11 @@ require('../common');
const stream = require('stream'); const stream = require('stream');
const REPL = require('internal/repl'); const REPL = require('internal/repl');
const assert = require('assert'); const assert = require('assert');
const debug = require('util').debuglog('test'); const inspect = require('util').inspect;
const tests = [ const tests = [
{ {
env: { TERM: 'xterm-256' }, env: {},
expected: { terminal: true, useColors: true } expected: { terminal: true, useColors: true }
}, },
{ {
@ -30,33 +30,35 @@ const tests = [
expected: { terminal: false, useColors: false } expected: { terminal: false, useColors: false }
}, },
{ {
env: { NODE_NO_READLINE: '0', TERM: 'xterm-256' }, env: { NODE_NO_READLINE: '0' },
expected: { terminal: true, useColors: true } expected: { terminal: true, useColors: true }
} }
]; ];
const originalEnv = process.env;
function run(test) { function run(test) {
const env = test.env; const env = test.env;
const expected = test.expected; const expected = test.expected;
process.env = { ...originalEnv, ...env };
const opts = { const opts = {
terminal: true, terminal: true,
input: new stream.Readable({ read() {} }), input: new stream.Readable({ read() {} }),
output: new stream.Writable({ write() {} }) output: new stream.Writable({ write() {} })
}; };
REPL.createInternalRepl(opts, (repl) => { Object.assign(process.env, env);
debug(env);
const { terminal, useColors } = repl; REPL.createInternalRepl(process.env, opts, function(err, repl) {
assert.deepStrictEqual({ terminal, useColors }, expected); assert.ifError(err);
assert.strictEqual(repl.terminal, expected.terminal,
`Expected ${inspect(expected)} with ${inspect(env)}`);
assert.strictEqual(repl.useColors, expected.useColors,
`Expected ${inspect(expected)} with ${inspect(env)}`);
for (const key of Object.keys(env)) {
delete process.env[key];
}
repl.close(); repl.close();
if (tests.length)
run(tests.shift());
}); });
} }
run(tests.shift()); tests.forEach(run);

View File

@ -521,8 +521,6 @@ function cleanupTmpFile() {
return true; return true;
} }
const originalEnv = process.env;
function runTest() { function runTest() {
const opts = tests.shift(); const opts = tests.shift();
if (!opts) return; // All done if (!opts) return; // All done
@ -537,9 +535,7 @@ function runTest() {
const lastChunks = []; const lastChunks = [];
let i = 0; let i = 0;
process.env = { ...originalEnv, ...opts.env }; REPL.createInternalRepl(opts.env, {
REPL.createInternalRepl({
input: new ActionStream(), input: new ActionStream(),
output: new stream.Writable({ output: new stream.Writable({
write(chunk, _, next) { write(chunk, _, next) {
@ -574,7 +570,12 @@ function runTest() {
useColors: false, useColors: false,
preview: opts.preview, preview: opts.preview,
terminal: true terminal: true
}, function(repl) { }, function(err, repl) {
if (err) {
console.error(`Failed test # ${numtests - tests.length}`);
throw err;
}
repl.once('close', () => { repl.once('close', () => {
if (opts.clean) if (opts.clean)
cleanupTmpFile(); cleanupTmpFile();

View File

@ -35,7 +35,9 @@ const tmpdir = require('../common/tmpdir');
tmpdir.refresh(); tmpdir.refresh();
const replHistoryPath = path.join(tmpdir.path, '.node_repl_history'); const replHistoryPath = path.join(tmpdir.path, '.node_repl_history');
const checkResults = common.mustCall((repl) => { const checkResults = common.mustCall(function(err, r) {
assert.ifError(err);
const stat = fs.statSync(replHistoryPath); const stat = fs.statSync(replHistoryPath);
const fileMode = stat.mode & 0o777; const fileMode = stat.mode & 0o777;
assert.strictEqual( assert.strictEqual(
@ -43,13 +45,12 @@ const checkResults = common.mustCall((repl) => {
`REPL history file should be mode 0600 but was 0${fileMode.toString(8)}`); `REPL history file should be mode 0600 but was 0${fileMode.toString(8)}`);
// Close the REPL // Close the REPL
repl.input.emit('keypress', '', { ctrl: true, name: 'd' }); r.input.emit('keypress', '', { ctrl: true, name: 'd' });
repl.input.end(); r.input.end();
}); });
process.env.NODE_REPL_HISTORY = replHistoryPath;
repl.createInternalRepl( repl.createInternalRepl(
{ NODE_REPL_HISTORY: replHistoryPath },
{ {
terminal: true, terminal: true,
input: stream, input: stream,

View File

@ -42,7 +42,6 @@ common.expectWarning({
// Create a dummy stream that does nothing // Create a dummy stream that does nothing
const stream = new ArrayStream(); const stream = new ArrayStream();
stream.hasColors = () => true;
// 1, mostly defaults // 1, mostly defaults
const r1 = repl.start({ const r1 = repl.start({

View File

@ -191,8 +191,6 @@ fs.createReadStream(historyFixturePath)
const runTestWrap = common.mustCall(runTest, numtests); const runTestWrap = common.mustCall(runTest, numtests);
const originalEnv = process.env;
function runTest(assertCleaned) { function runTest(assertCleaned) {
const opts = tests.shift(); const opts = tests.shift();
if (!opts) return; // All done if (!opts) return; // All done
@ -210,6 +208,7 @@ function runTest(assertCleaned) {
} }
} }
const env = opts.env;
const test = opts.test; const test = opts.test;
const expected = opts.expected; const expected = opts.expected;
const clean = opts.clean; const clean = opts.clean;
@ -217,9 +216,7 @@ function runTest(assertCleaned) {
if (before) before(); if (before) before();
process.env = { ...originalEnv, ...opts.env }; REPL.createInternalRepl(env, {
REPL.createInternalRepl({
input: new ActionStream(), input: new ActionStream(),
output: new stream.Writable({ output: new stream.Writable({
write(chunk, _, next) { write(chunk, _, next) {
@ -242,7 +239,12 @@ function runTest(assertCleaned) {
prompt, prompt,
useColors: false, useColors: false,
terminal: true terminal: true
}, function(repl) { }, function(err, repl) {
if (err) {
console.error(`Failed test # ${numtests - tests.length}`);
throw err;
}
repl.once('close', () => { repl.once('close', () => {
if (repl._flushing) { if (repl._flushing) {
repl.once('flushHistory', onClose); repl.once('flushHistory', onClose);

View File

@ -282,9 +282,6 @@ function cleanupTmpFile() {
return true; return true;
} }
const originalEnv = { ...process.env };
function runTest() { function runTest() {
const opts = tests.shift(); const opts = tests.shift();
if (!opts) return; // All done if (!opts) return; // All done
@ -300,9 +297,7 @@ function runTest() {
const lastChunks = []; const lastChunks = [];
let i = 0; let i = 0;
process.env = { ...originalEnv, ...opts.env }; REPL.createInternalRepl(opts.env, {
REPL.createInternalRepl({
input: new ActionStream(), input: new ActionStream(),
output: new stream.Writable({ output: new stream.Writable({
write(chunk, _, next) { write(chunk, _, next) {
@ -335,7 +330,12 @@ function runTest() {
prompt, prompt,
useColors: opts.useColors || false, useColors: opts.useColors || false,
terminal: true terminal: true
}, function(repl) { }, function(err, repl) {
if (err) {
console.error(`Failed test # ${numtests - tests.length}`);
throw err;
}
repl.once('close', () => { repl.once('close', () => {
if (opts.clean) if (opts.clean)
cleanupTmpFile(); cleanupTmpFile();

View File

@ -14,19 +14,23 @@ const globalTestCases = [
[undefined, 'undefined'] [undefined, 'undefined']
]; ];
const globalTest = (cb, output) => (repl) => { const globalTest = (useGlobal, cb, output) => (err, repl) => {
if (err)
return cb(err);
let str = ''; let str = '';
output.on('data', (data) => (str += data)); output.on('data', (data) => (str += data));
global.lunch = 'tacos'; global.lunch = 'tacos';
repl.write('global.lunch;\n'); repl.write('global.lunch;\n');
repl.close(); repl.close();
delete global.lunch; delete global.lunch;
cb(str.trim()); cb(null, str.trim());
}; };
// Test how the global object behaves in each state for useGlobal // Test how the global object behaves in each state for useGlobal
for (const [option, expected] of globalTestCases) { for (const [option, expected] of globalTestCases) {
runRepl(option, globalTest, common.mustCall((output) => { runRepl(option, globalTest, common.mustCall((err, output) => {
assert.ifError(err);
assert.strictEqual(output, expected); assert.strictEqual(output, expected);
})); }));
} }
@ -39,7 +43,10 @@ for (const [option, expected] of globalTestCases) {
// suite is aware of it, causing a failure to be flagged. // suite is aware of it, causing a failure to be flagged.
// //
const processTestCases = [false, undefined]; const processTestCases = [false, undefined];
const processTest = (cb, output) => (repl) => { const processTest = (useGlobal, cb, output) => (err, repl) => {
if (err)
return cb(err);
let str = ''; let str = '';
output.on('data', (data) => (str += data)); output.on('data', (data) => (str += data));
@ -47,11 +54,12 @@ const processTest = (cb, output) => (repl) => {
repl.write('let process;\n'); repl.write('let process;\n');
repl.write('21 * 2;\n'); repl.write('21 * 2;\n');
repl.close(); repl.close();
cb(str.trim()); cb(null, str.trim());
}; };
for (const option of processTestCases) { for (const option of processTestCases) {
runRepl(option, processTest, common.mustCall((output) => { runRepl(option, processTest, common.mustCall((err, output) => {
assert.ifError(err);
assert.strictEqual(output, 'undefined\n42'); assert.strictEqual(output, 'undefined\n42');
})); }));
} }
@ -68,5 +76,8 @@ function runRepl(useGlobal, testFunc, cb) {
prompt: '' prompt: ''
}; };
repl.createInternalRepl(opts, testFunc(cb, opts.output)); repl.createInternalRepl(
process.env,
opts,
testFunc(useGlobal, cb, opts.output));
} }