mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
test: add new startNewREPLSever testing utility
PR-URL: https://github.com/nodejs/node/pull/59964 Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
This commit is contained in:
parent
c6316f9db9
commit
9ac571d0d5
31
test/common/repl.js
Normal file
31
test/common/repl.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const repl = require('node:repl');
|
||||
const assert = require('node:assert');
|
||||
|
||||
function startNewREPLServer(replOpts = {}, testingOpts = {}) {
|
||||
const input = new ArrayStream();
|
||||
const output = new ArrayStream();
|
||||
|
||||
output.accumulator = '';
|
||||
output.write = (data) => (output.accumulator += `${data}`.replaceAll('\r', ''));
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output,
|
||||
terminal: true,
|
||||
allowBlockingCompletions: true,
|
||||
...replOpts,
|
||||
});
|
||||
|
||||
if (!testingOpts.disableDomainErrorAssert) {
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
}
|
||||
|
||||
return { replServer, input, output };
|
||||
}
|
||||
|
||||
module.exports = { startNewREPLServer };
|
||||
|
|
@ -22,12 +22,12 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('assert');
|
||||
const util = require('util');
|
||||
const repl = require('repl');
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
repl.start('', putIn, null, true);
|
||||
startNewREPLServer({ input: putIn, output: putIn, useGlobal: true, terminal: false });
|
||||
|
||||
test1();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,19 +4,11 @@ const common = require('../common');
|
|||
const assert = require('node:assert');
|
||||
const { describe, test } = require('node:test');
|
||||
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const repl = require('node:repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
function runCompletionTests(replInit, tests) {
|
||||
const stream = new ArrayStream();
|
||||
const testRepl = repl.start({ stream });
|
||||
|
||||
// Some errors are passed to the domain
|
||||
testRepl._domain.on('error', assert.ifError);
|
||||
|
||||
testRepl.write(replInit);
|
||||
testRepl.write('\n');
|
||||
const { replServer: testRepl, input } = startNewREPLServer();
|
||||
input.run([replInit]);
|
||||
|
||||
tests.forEach(([query, expectedCompletions]) => {
|
||||
testRepl.complete(query, common.mustCall((error, data) => {
|
||||
|
|
|
|||
|
|
@ -1,38 +1,28 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const vm = require('vm');
|
||||
|
||||
// Create a dummy stream that does nothing.
|
||||
const stream = new ArrayStream();
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
// Test context when useGlobal is false.
|
||||
{
|
||||
const r = repl.start({
|
||||
input: stream,
|
||||
output: stream,
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
terminal: false,
|
||||
useGlobal: false
|
||||
});
|
||||
|
||||
let output = '';
|
||||
stream.write = function(d) {
|
||||
output += d;
|
||||
};
|
||||
|
||||
// Ensure that the repl context gets its own "console" instance.
|
||||
assert(r.context.console);
|
||||
assert(replServer.context.console);
|
||||
|
||||
// Ensure that the repl console instance is not the global one.
|
||||
assert.notStrictEqual(r.context.console, console);
|
||||
assert.notStrictEqual(r.context.Object, Object);
|
||||
assert.notStrictEqual(replServer.context.console, console);
|
||||
assert.notStrictEqual(replServer.context.Object, Object);
|
||||
|
||||
stream.run(['({} instanceof Object)']);
|
||||
replServer.write('({} instanceof Object)\n');
|
||||
|
||||
assert.strictEqual(output, 'true\n> ');
|
||||
assert.strictEqual(output.accumulator, 'true\n');
|
||||
|
||||
const context = r.createContext();
|
||||
const context = replServer.createContext();
|
||||
// Ensure that the repl context gets its own "console" instance.
|
||||
assert(context.console instanceof require('console').Console);
|
||||
|
||||
|
|
@ -41,44 +31,46 @@ const stream = new ArrayStream();
|
|||
|
||||
// Ensure that the repl console instance is writable.
|
||||
context.console = 'foo';
|
||||
r.close();
|
||||
replServer.close();
|
||||
}
|
||||
|
||||
// Test for context side effects.
|
||||
{
|
||||
const server = repl.start({ input: stream, output: stream });
|
||||
const { replServer } = startNewREPLServer({
|
||||
useGlobal: false
|
||||
});
|
||||
|
||||
assert.ok(!server.underscoreAssigned);
|
||||
assert.strictEqual(server.lines.length, 0);
|
||||
assert.ok(!replServer.underscoreAssigned);
|
||||
assert.strictEqual(replServer.lines.length, 0);
|
||||
|
||||
// An assignment to '_' in the repl server
|
||||
server.write('_ = 500;\n');
|
||||
assert.ok(server.underscoreAssigned);
|
||||
assert.strictEqual(server.lines.length, 1);
|
||||
assert.strictEqual(server.lines[0], '_ = 500;');
|
||||
assert.strictEqual(server.last, 500);
|
||||
replServer.write('_ = 500;\n');
|
||||
assert.ok(replServer.underscoreAssigned);
|
||||
assert.strictEqual(replServer.lines.length, 1);
|
||||
assert.strictEqual(replServer.lines[0], '_ = 500;');
|
||||
assert.strictEqual(replServer.last, 500);
|
||||
|
||||
// Use the server to create a new context
|
||||
const context = server.createContext();
|
||||
const context = replServer.createContext();
|
||||
|
||||
// Ensure that creating a new context does not
|
||||
// have side effects on the server
|
||||
assert.ok(server.underscoreAssigned);
|
||||
assert.strictEqual(server.lines.length, 1);
|
||||
assert.strictEqual(server.lines[0], '_ = 500;');
|
||||
assert.strictEqual(server.last, 500);
|
||||
assert.ok(replServer.underscoreAssigned);
|
||||
assert.strictEqual(replServer.lines.length, 1);
|
||||
assert.strictEqual(replServer.lines[0], '_ = 500;');
|
||||
assert.strictEqual(replServer.last, 500);
|
||||
|
||||
// Reset the server context
|
||||
server.resetContext();
|
||||
assert.ok(!server.underscoreAssigned);
|
||||
assert.strictEqual(server.lines.length, 0);
|
||||
replServer.resetContext();
|
||||
assert.ok(!replServer.underscoreAssigned);
|
||||
assert.strictEqual(replServer.lines.length, 0);
|
||||
|
||||
// Ensure that assigning to '_' in the new context
|
||||
// does not change the value in our server.
|
||||
assert.ok(!server.underscoreAssigned);
|
||||
assert.ok(!replServer.underscoreAssigned);
|
||||
vm.runInContext('_ = 1000;\n', context);
|
||||
|
||||
assert.ok(!server.underscoreAssigned);
|
||||
assert.strictEqual(server.lines.length, 0);
|
||||
server.close();
|
||||
assert.ok(!replServer.underscoreAssigned);
|
||||
assert.strictEqual(replServer.lines.length, 0);
|
||||
replServer.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
common.skipIfInspectorDisabled();
|
||||
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const testingReplPrompt = '_REPL_TESTING_PROMPT_>';
|
||||
|
||||
// Processes some input in a REPL instance and returns a promise that
|
||||
// resolves to the produced output (as a string).
|
||||
function getReplRunOutput(input, replOptions) {
|
||||
function getReplRunOutput(inputStr, replOptions) {
|
||||
return new Promise((resolve) => {
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
const { replServer, input, output } = startNewREPLServer({ prompt: testingReplPrompt, ...replOptions });
|
||||
|
||||
const replServer = repl.start({
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
prompt: testingReplPrompt,
|
||||
...replOptions,
|
||||
});
|
||||
output.accumulator = '';
|
||||
|
||||
let output = '';
|
||||
|
||||
outputStream.write = (chunk) => {
|
||||
output += chunk;
|
||||
output.write = (chunk) => {
|
||||
output.accumulator += chunk;
|
||||
// The prompt appears after the input has been processed
|
||||
if (output.includes(testingReplPrompt)) {
|
||||
if (output.accumulator.includes(testingReplPrompt)) {
|
||||
replServer.close();
|
||||
resolve(output);
|
||||
resolve(output.accumulator);
|
||||
}
|
||||
};
|
||||
|
||||
inputStream.emit('data', input);
|
||||
input.emit('data', inputStr);
|
||||
|
||||
inputStream.run(['']);
|
||||
input.run(['']);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('assert');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
const repl = require('repl');
|
||||
const testingReplPrompt = '_REPL_TESTING_PROMPT_>';
|
||||
|
||||
// Processes some input in a REPL instance and returns a promise that
|
||||
// resolves to the produced output (as a string).
|
||||
function getReplRunOutput(input, replOptions) {
|
||||
function getReplRunOutput(inputStr, replOptions) {
|
||||
return new Promise((resolve) => {
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
const { replServer, input, output } = startNewREPLServer({ prompt: testingReplPrompt, ...replOptions });
|
||||
|
||||
const testingReplPrompt = '_REPL_TESTING_PROMPT_>';
|
||||
output.accumulator = '';
|
||||
|
||||
const replServer = repl.start({
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
prompt: testingReplPrompt,
|
||||
...replOptions,
|
||||
});
|
||||
|
||||
let output = '';
|
||||
|
||||
outputStream.write = (chunk) => {
|
||||
output += chunk;
|
||||
output.write = (chunk) => {
|
||||
output.accumulator += chunk;
|
||||
// The prompt appears after the input has been processed
|
||||
if (output.includes(testingReplPrompt)) {
|
||||
if (output.accumulator.includes(testingReplPrompt)) {
|
||||
replServer.close();
|
||||
resolve(output);
|
||||
resolve(output.accumulator);
|
||||
}
|
||||
};
|
||||
|
||||
inputStream.emit('data', input);
|
||||
input.emit('data', inputStr);
|
||||
|
||||
inputStream.run(['']);
|
||||
input.run(['']);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -62,23 +52,23 @@ describe('repl with custom eval', { concurrency: true }, () => {
|
|||
|
||||
it('provides a repl context to the eval callback', async () => {
|
||||
const context = await new Promise((resolve) => {
|
||||
const r = repl.start({
|
||||
const { replServer } = startNewREPLServer({
|
||||
eval: (_cmd, context) => resolve(context),
|
||||
});
|
||||
r.context = { foo: 'bar' };
|
||||
r.write('\n.exit\n');
|
||||
replServer.context = { foo: 'bar' };
|
||||
replServer.write('\n.exit\n');
|
||||
});
|
||||
assert.strictEqual(context.foo, 'bar');
|
||||
});
|
||||
|
||||
it('provides the global context to the eval callback', async () => {
|
||||
const context = await new Promise((resolve) => {
|
||||
const r = repl.start({
|
||||
useGlobal: true,
|
||||
const { replServer } = startNewREPLServer({
|
||||
eval: (_cmd, context) => resolve(context),
|
||||
useGlobal: true
|
||||
});
|
||||
global.foo = 'global_foo';
|
||||
r.write('\n.exit\n');
|
||||
replServer.write('\n.exit\n');
|
||||
});
|
||||
|
||||
assert.strictEqual(context.foo, 'global_foo');
|
||||
|
|
@ -88,12 +78,12 @@ describe('repl with custom eval', { concurrency: true }, () => {
|
|||
it('inherits variables from the global context but does not use it afterwords if `useGlobal` is false', async () => {
|
||||
global.bar = 'global_bar';
|
||||
const context = await new Promise((resolve) => {
|
||||
const r = repl.start({
|
||||
const { replServer } = startNewREPLServer({
|
||||
useGlobal: false,
|
||||
eval: (_cmd, context) => resolve(context),
|
||||
});
|
||||
global.baz = 'global_baz';
|
||||
r.write('\n.exit\n');
|
||||
replServer.write('\n.exit\n');
|
||||
});
|
||||
|
||||
assert.strictEqual(context.bar, 'global_bar');
|
||||
|
|
@ -111,10 +101,10 @@ describe('repl with custom eval', { concurrency: true }, () => {
|
|||
*/
|
||||
it('preserves the original input', async () => {
|
||||
const cmd = await new Promise((resolve) => {
|
||||
const r = repl.start({
|
||||
const { replServer } = startNewREPLServer({
|
||||
eval: (cmd) => resolve(cmd),
|
||||
});
|
||||
r.write('function f() {}\n.exit\n');
|
||||
replServer.write('function f() {}\n.exit\n');
|
||||
});
|
||||
assert.strictEqual(cmd, 'function f() {}\n');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,25 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const stream = require('stream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
|
||||
let output = '';
|
||||
const inputStream = new stream.PassThrough();
|
||||
const outputStream = new stream.PassThrough();
|
||||
outputStream.on('data', function(d) {
|
||||
output += d;
|
||||
});
|
||||
|
||||
const r = repl.start({
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
terminal: true
|
||||
});
|
||||
const { replServer: replServer, input } = startNewREPLServer({ prompt: '> ', terminal: true, output: outputStream });
|
||||
|
||||
r.defineCommand('say1', {
|
||||
replServer.defineCommand('say1', {
|
||||
help: 'help for say1',
|
||||
action: function(thing) {
|
||||
output = '';
|
||||
|
|
@ -28,21 +23,21 @@ r.defineCommand('say1', {
|
|||
}
|
||||
});
|
||||
|
||||
r.defineCommand('say2', function() {
|
||||
replServer.defineCommand('say2', function() {
|
||||
output = '';
|
||||
this.output.write('hello from say2\n');
|
||||
this.displayPrompt();
|
||||
});
|
||||
|
||||
inputStream.write('.help\n');
|
||||
input.run(['.help\n']);
|
||||
assert.match(output, /\n\.say1 {5}help for say1\n/);
|
||||
assert.match(output, /\n\.say2\n/);
|
||||
inputStream.write('.say1 node developer\n');
|
||||
input.run(['.say1 node developer\n']);
|
||||
assert.ok(output.startsWith('hello node developer\n'),
|
||||
`say1 output starts incorrectly: "${output}"`);
|
||||
assert.ok(output.includes('> '),
|
||||
`say1 output does not include prompt: "${output}"`);
|
||||
inputStream.write('.say2 node developer\n');
|
||||
input.run(['.say2 node developer\n']);
|
||||
assert.ok(output.startsWith('hello from say2\n'),
|
||||
`say2 output starts incorrectly: "${output}"`);
|
||||
assert.ok(output.includes('> '),
|
||||
|
|
|
|||
|
|
@ -21,14 +21,18 @@
|
|||
|
||||
'use strict';
|
||||
require('../common');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const repl = require('repl');
|
||||
const stream = new ArrayStream();
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
repl.start('', putIn);
|
||||
startNewREPLServer({
|
||||
input: stream,
|
||||
output: stream,
|
||||
terminal: false,
|
||||
});
|
||||
|
||||
putIn.write = function(data) {
|
||||
stream.write = function(data) {
|
||||
// Don't use assert for this because the domain might catch it, and
|
||||
// give a false negative. Don't throw, just print and exit.
|
||||
if (data === 'OK\n') {
|
||||
|
|
@ -39,7 +43,7 @@ putIn.write = function(data) {
|
|||
}
|
||||
};
|
||||
|
||||
putIn.run([
|
||||
stream.run([
|
||||
'require("domain").create().on("error", function() { console.log("OK") })' +
|
||||
'.run(function() { throw new Error("threw") })',
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
if (process.env.TERM === 'dumb') {
|
||||
common.skip('skipping - dumb terminal');
|
||||
|
|
@ -15,30 +14,24 @@ if (process.env.TERM === 'dumb') {
|
|||
const terminalCode = '\u001b[1G\u001b[0J> \u001b[3G';
|
||||
const terminalCodeRegex = new RegExp(terminalCode.replace(/\[/g, '\\['), 'g');
|
||||
|
||||
function run({ input, output, event, checkTerminalCodes = true }) {
|
||||
const stream = new ArrayStream();
|
||||
let found = '';
|
||||
|
||||
stream.write = (msg) => found += msg.replace('\r', '');
|
||||
|
||||
function run({ input: inputStr, output: outputStr, event, checkTerminalCodes = true }) {
|
||||
let expected =
|
||||
`${terminalCode}.editor\n` +
|
||||
'// Entering editor mode (Ctrl+D to finish, Ctrl+C to cancel)\n' +
|
||||
`${input}${output}\n${terminalCode}`;
|
||||
`${inputStr}${outputStr}\n${terminalCode}`;
|
||||
|
||||
const replServer = repl.start({
|
||||
const { replServer, input, output } = startNewREPLServer({
|
||||
prompt: '> ',
|
||||
terminal: true,
|
||||
input: stream,
|
||||
output: stream,
|
||||
useColors: false
|
||||
});
|
||||
|
||||
stream.emit('data', '.editor\n');
|
||||
stream.emit('data', input);
|
||||
input.emit('data', '.editor\n');
|
||||
input.emit('data', inputStr);
|
||||
replServer.write('', event);
|
||||
replServer.close();
|
||||
|
||||
let found = output.accumulator;
|
||||
if (!checkTerminalCodes) {
|
||||
found = found.replace(terminalCodeRegex, '').replace(/\n/g, '');
|
||||
expected = expected.replace(terminalCodeRegex, '').replace(/\n/g, '');
|
||||
|
|
@ -79,22 +72,15 @@ const tests = [
|
|||
tests.forEach(run);
|
||||
|
||||
// Auto code alignment for .editor mode
|
||||
function testCodeAlignment({ input, cursor = 0, line = '' }) {
|
||||
const stream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
|
||||
stream.write = () => { throw new Error('Writing not allowed!'); };
|
||||
|
||||
const replServer = repl.start({
|
||||
function testCodeAlignment({ input: inputStr, cursor = 0, line = '' }) {
|
||||
const { replServer, input } = startNewREPLServer({
|
||||
prompt: '> ',
|
||||
terminal: true,
|
||||
input: stream,
|
||||
output: outputStream,
|
||||
useColors: false
|
||||
});
|
||||
|
||||
stream.emit('data', '.editor\n');
|
||||
input.split('').forEach((ch) => stream.emit('data', ch));
|
||||
input.emit('data', '.editor\n');
|
||||
inputStr.split('').forEach((ch) => input.emit('data', ch));
|
||||
// Test the content of current line and the cursor position
|
||||
assert.strictEqual(line, replServer.line);
|
||||
assert.strictEqual(cursor, replServer.cursor);
|
||||
|
|
|
|||
|
|
@ -1,27 +1,23 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
{
|
||||
let evalCalledWithExpectedArgs = false;
|
||||
let evalCalledWithExpectedArgs = false;
|
||||
|
||||
const options = {
|
||||
eval: common.mustCall((cmd, context) => {
|
||||
// Assertions here will not cause the test to exit with an error code
|
||||
// so set a boolean that is checked later instead.
|
||||
evalCalledWithExpectedArgs = (cmd === '\n');
|
||||
})
|
||||
};
|
||||
const { replServer } = startNewREPLServer({
|
||||
eval: common.mustCall((cmd, context) => {
|
||||
// Assertions here will not cause the test to exit with an error code
|
||||
// so set a boolean that is checked later instead.
|
||||
evalCalledWithExpectedArgs = (cmd === '\n');
|
||||
})
|
||||
});
|
||||
|
||||
const r = repl.start(options);
|
||||
|
||||
try {
|
||||
// Empty strings should be sent to the repl's eval function
|
||||
r.write('\n');
|
||||
} finally {
|
||||
r.write('.exit\n');
|
||||
}
|
||||
|
||||
assert(evalCalledWithExpectedArgs);
|
||||
try {
|
||||
// Empty strings should be sent to the repl's eval function
|
||||
replServer.write('\n');
|
||||
} finally {
|
||||
replServer.write('.exit\n');
|
||||
}
|
||||
|
||||
assert(evalCalledWithExpectedArgs);
|
||||
|
|
|
|||
|
|
@ -21,28 +21,20 @@
|
|||
|
||||
'use strict';
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
let terminalExit = 0;
|
||||
let regularExit = 0;
|
||||
|
||||
// Create a dummy stream that does nothing
|
||||
const stream = new ArrayStream();
|
||||
|
||||
function testTerminalMode() {
|
||||
const r1 = repl.start({
|
||||
input: stream,
|
||||
output: stream,
|
||||
terminal: true
|
||||
});
|
||||
const { replServer, input } = startNewREPLServer({ terminal: true });
|
||||
|
||||
process.nextTick(function() {
|
||||
// Manually fire a ^D keypress
|
||||
stream.emit('data', '\u0004');
|
||||
input.emit('data', '\u0004');
|
||||
});
|
||||
|
||||
r1.on('exit', function() {
|
||||
replServer.on('exit', function() {
|
||||
// Should be fired from the simulated ^D keypress
|
||||
terminalExit++;
|
||||
testRegularMode();
|
||||
|
|
@ -50,17 +42,13 @@ function testTerminalMode() {
|
|||
}
|
||||
|
||||
function testRegularMode() {
|
||||
const r2 = repl.start({
|
||||
input: stream,
|
||||
output: stream,
|
||||
terminal: false
|
||||
});
|
||||
const { replServer, input } = startNewREPLServer({ terminal: true });
|
||||
|
||||
process.nextTick(function() {
|
||||
stream.emit('end');
|
||||
input.emit('end');
|
||||
});
|
||||
|
||||
r2.on('exit', function() {
|
||||
replServer.on('exit', function() {
|
||||
// Should be fired from the simulated 'end' event
|
||||
regularExit++;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const repl = require('node:repl');
|
||||
const stream = require('node:stream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('node:assert');
|
||||
|
||||
// This test checks that an eval function returning an error in its callback
|
||||
|
|
@ -13,26 +12,18 @@ const assert = require('node:assert');
|
|||
const close$ = Promise.withResolvers();
|
||||
const eval$ = Promise.withResolvers();
|
||||
|
||||
const input = new stream.PassThrough();
|
||||
const output = new stream.PassThrough();
|
||||
|
||||
const replServer = repl.start({
|
||||
input,
|
||||
output,
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
eval(_cmd, _context, _file, cb) {
|
||||
close$.promise.then(() => {
|
||||
cb(new Error('Error returned from the eval callback'));
|
||||
eval$.resolve();
|
||||
});
|
||||
},
|
||||
}, {
|
||||
disableDomainErrorAssert: true,
|
||||
});
|
||||
|
||||
let outputStr = '';
|
||||
output.on('data', (data) => {
|
||||
outputStr += data;
|
||||
});
|
||||
|
||||
input.write('\n');
|
||||
replServer.write('\n');
|
||||
|
||||
replServer.close();
|
||||
close$.resolve();
|
||||
|
|
@ -41,5 +32,5 @@ const assert = require('node:assert');
|
|||
|
||||
await eval$.promise;
|
||||
|
||||
assert.match(outputStr, /Uncaught Error: Error returned from the eval callback/);
|
||||
assert.match(output.accumulator, /Uncaught Error: Error returned from the eval callback/);
|
||||
})().then(common.mustCall());
|
||||
|
|
|
|||
|
|
@ -2,36 +2,18 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const stream = require('stream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const r = initRepl();
|
||||
const { replServer } = startNewREPLServer({
|
||||
useColors: false,
|
||||
terminal: false
|
||||
});
|
||||
|
||||
r.input.emit('data', 'function a() { return 42; } (1)\n');
|
||||
r.input.emit('data', 'a\n');
|
||||
r.input.emit('data', '.exit\n');
|
||||
r.once('exit', common.mustCall());
|
||||
replServer.input.emit('data', 'function a() { return 42; } (1)\n');
|
||||
replServer.input.emit('data', 'a\n');
|
||||
replServer.input.emit('data', '.exit\n');
|
||||
replServer.once('exit', common.mustCall());
|
||||
|
||||
const expected = '1\n[Function: a]\n';
|
||||
const got = r.output.accumulator.join('');
|
||||
const got = replServer.output.accumulator;
|
||||
assert.strictEqual(got, expected);
|
||||
|
||||
function initRepl() {
|
||||
const input = new stream();
|
||||
input.write = input.pause = input.resume = () => {};
|
||||
input.readable = true;
|
||||
|
||||
const output = new stream();
|
||||
output.writable = true;
|
||||
output.accumulator = [];
|
||||
|
||||
output.write = (data) => output.accumulator.push(data);
|
||||
|
||||
return repl.start({
|
||||
input,
|
||||
output,
|
||||
useColors: false,
|
||||
terminal: false,
|
||||
prompt: ''
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
common.skipIfInspectorDisabled();
|
||||
|
||||
// This test verifies that the V8 inspector API is usable in the REPL.
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
let output = '';
|
||||
putIn.write = function(data) {
|
||||
output += data;
|
||||
};
|
||||
const { replServer, input, output } = startNewREPLServer();
|
||||
|
||||
const testMe = repl.start('', putIn);
|
||||
input.run(['const myVariable = 42']);
|
||||
|
||||
putIn.run(['const myVariable = 42']);
|
||||
|
||||
testMe.complete('myVar', common.mustCall((error, data) => {
|
||||
replServer.complete('myVar', common.mustCall((error, data) => {
|
||||
assert.deepStrictEqual(data, [['myVariable'], 'myVar']);
|
||||
}));
|
||||
|
||||
putIn.run([
|
||||
input.run([
|
||||
'const inspector = require("inspector")',
|
||||
'const session = new inspector.Session()',
|
||||
'session.connect()',
|
||||
|
|
@ -31,5 +24,5 @@ putIn.run([
|
|||
'session.disconnect()',
|
||||
]);
|
||||
|
||||
assert(output.includes(
|
||||
assert(output.accumulator.includes(
|
||||
"null { result: { type: 'number', value: 2, description: '2' } }"));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
// Regression test for https://github.com/nodejs/node/issues/6802
|
||||
const input = new ArrayStream();
|
||||
repl.start({ input, output: process.stdout, useGlobal: true });
|
||||
const { input } = startNewREPLServer({ useGlobal: true }, { disableDomainErrorAssert: true });
|
||||
input.run(['let process']);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
if (process.env.TERM === 'dumb') {
|
||||
common.skip('skipping - dumb terminal');
|
||||
|
|
@ -24,21 +23,11 @@ const eat = (food) => '<nom nom nom>';
|
|||
undefined
|
||||
`;
|
||||
|
||||
let accum = '';
|
||||
const { replServer, output } = startNewREPLServer();
|
||||
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
|
||||
outputStream.write = (data) => accum += data.replace('\r', '');
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
terminal: true,
|
||||
useColors: false
|
||||
});
|
||||
|
||||
r.write(`${command}\n`);
|
||||
assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected);
|
||||
r.close();
|
||||
replServer.write(`${command}\n`);
|
||||
assert.strictEqual(
|
||||
output.accumulator.replace(terminalCodeRegex, ''),
|
||||
expected
|
||||
);
|
||||
replServer.close();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
if (process.env.TERM === 'dumb') {
|
||||
common.skip('skipping - dumb terminal');
|
||||
|
|
@ -24,21 +23,8 @@ const eat = (food) => '<nom nom nom>';
|
|||
undefined
|
||||
`;
|
||||
|
||||
let accum = '';
|
||||
const { replServer, output } = startNewREPLServer();
|
||||
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
|
||||
outputStream.write = (data) => accum += data.replace('\r', '');
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
terminal: true,
|
||||
useColors: false
|
||||
});
|
||||
|
||||
r.write(`${command}\n`);
|
||||
assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected);
|
||||
r.close();
|
||||
replServer.write(`${command}\n`);
|
||||
assert.strictEqual(output.accumulator.replace(terminalCodeRegex, ''), expected);
|
||||
replServer.close();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const Stream = require('stream');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
if (process.env.TERM === 'dumb') {
|
||||
common.skip('skipping - dumb terminal');
|
||||
|
|
@ -20,26 +20,27 @@ tests.forEach(function(test) {
|
|||
});
|
||||
|
||||
function testSloppyMode() {
|
||||
const cli = initRepl(repl.REPL_MODE_SLOPPY);
|
||||
const { input, output } = startNewREPLServer({ replMode: repl.REPL_MODE_SLOPPY, terminal: false, prompt: '> ' });
|
||||
|
||||
cli.input.emit('data', 'x = 3\n');
|
||||
assert.strictEqual(cli.output.accumulator.join(''), '> 3\n> ');
|
||||
cli.output.accumulator.length = 0;
|
||||
input.emit('data', 'x = 3\n');
|
||||
assert.strictEqual(output.accumulator, '> 3\n> ');
|
||||
output.accumulator = '';
|
||||
|
||||
cli.input.emit('data', 'let y = 3\n');
|
||||
assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> ');
|
||||
input.emit('data', 'let y = 3\n');
|
||||
assert.strictEqual(output.accumulator, 'undefined\n> ');
|
||||
}
|
||||
|
||||
function testStrictMode() {
|
||||
const cli = initRepl(repl.REPL_MODE_STRICT);
|
||||
const { input, output } = startNewREPLServer({ replMode: repl.REPL_MODE_STRICT, terminal: false, prompt: '> ' }, {
|
||||
disableDomainErrorAssert: true,
|
||||
});
|
||||
|
||||
cli.input.emit('data', 'x = 3\n');
|
||||
assert.match(cli.output.accumulator.join(''),
|
||||
/ReferenceError: x is not defined/);
|
||||
cli.output.accumulator.length = 0;
|
||||
input.emit('data', 'x = 3\n');
|
||||
assert.match(output.accumulator, /ReferenceError: x is not defined/);
|
||||
output.accumulator = '';
|
||||
|
||||
cli.input.emit('data', 'let y = 3\n');
|
||||
assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> ');
|
||||
input.emit('data', 'let y = 3\n');
|
||||
assert.strictEqual(output.accumulator, 'undefined\n> ');
|
||||
}
|
||||
|
||||
function testStrictModeTerminal() {
|
||||
|
|
@ -48,45 +49,21 @@ function testStrictModeTerminal() {
|
|||
return;
|
||||
}
|
||||
// Verify that ReferenceErrors are reported in strict mode previews.
|
||||
const cli = initRepl(repl.REPL_MODE_STRICT, {
|
||||
terminal: true
|
||||
});
|
||||
const { input, output } = startNewREPLServer({ replMode: repl.REPL_MODE_STRICT, prompt: '> ' });
|
||||
|
||||
cli.input.emit('data', 'xyz ');
|
||||
input.emit('data', 'xyz ');
|
||||
assert.ok(
|
||||
cli.output.accumulator.includes('\n// ReferenceError: xyz is not defined')
|
||||
output.accumulator.includes('\n// ReferenceError: xyz is not defined')
|
||||
);
|
||||
}
|
||||
|
||||
function testAutoMode() {
|
||||
const cli = initRepl(repl.REPL_MODE_MAGIC);
|
||||
const { input, output } = startNewREPLServer({ replMode: repl.REPL_MODE_MAGIC, terminal: false, prompt: '> ' });
|
||||
|
||||
cli.input.emit('data', 'x = 3\n');
|
||||
assert.strictEqual(cli.output.accumulator.join(''), '> 3\n> ');
|
||||
cli.output.accumulator.length = 0;
|
||||
input.emit('data', 'x = 3\n');
|
||||
assert.strictEqual(output.accumulator, '> 3\n> ');
|
||||
output.accumulator = '';
|
||||
|
||||
cli.input.emit('data', 'let y = 3\n');
|
||||
assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> ');
|
||||
}
|
||||
|
||||
function initRepl(mode, options) {
|
||||
const input = new Stream();
|
||||
input.write = input.pause = input.resume = () => {};
|
||||
input.readable = true;
|
||||
|
||||
const output = new Stream();
|
||||
output.write = output.pause = output.resume = function(buf) {
|
||||
output.accumulator.push(buf);
|
||||
};
|
||||
output.accumulator = [];
|
||||
output.writable = true;
|
||||
|
||||
return repl.start({
|
||||
input: input,
|
||||
output: output,
|
||||
useColors: false,
|
||||
terminal: false,
|
||||
replMode: mode,
|
||||
...options
|
||||
});
|
||||
input.emit('data', 'let y = 3\n');
|
||||
assert.strictEqual(output.accumulator, 'undefined\n> ');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,15 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const input = ['const foo = {', '};', 'foo'];
|
||||
|
||||
function run({ useColors }) {
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
let output = '';
|
||||
const { replServer, output } = startNewREPLServer({ useColors });
|
||||
|
||||
outputStream.write = (data) => { output += data.replace('\r', ''); };
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
terminal: true,
|
||||
useColors
|
||||
});
|
||||
|
||||
r.on('exit', common.mustCall(() => {
|
||||
const actual = output.split('\n');
|
||||
replServer.on('exit', common.mustCall(() => {
|
||||
const actual = output.accumulator.split('\n');
|
||||
|
||||
// Validate the output, which contains terminal escape codes.
|
||||
assert.strictEqual(actual.length, 6);
|
||||
|
|
@ -33,8 +21,8 @@ function run({ useColors }) {
|
|||
assert.strictEqual(actual[4], '{}');
|
||||
}));
|
||||
|
||||
inputStream.run(input);
|
||||
r.close();
|
||||
input.forEach((line) => replServer.write(`${line}\n`));
|
||||
replServer.close();
|
||||
}
|
||||
|
||||
run({ useColors: true });
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const stream = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({ terminal: false, input: stream, output: stream });
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.setupHistory('/nonexistent/file', common.mustSucceed(() => {
|
||||
replServer.close();
|
||||
|
|
|
|||
|
|
@ -1,23 +1,13 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const repl = require('repl');
|
||||
const assert = require('assert');
|
||||
const Stream = require('stream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const output = new Stream();
|
||||
let text = '';
|
||||
output.write = output.pause = output.resume = function(buf) {
|
||||
text += buf.toString();
|
||||
};
|
||||
const { replServer, output } = startNewREPLServer();
|
||||
|
||||
const replserver = repl.start({
|
||||
output: output,
|
||||
input: process.stdin
|
||||
});
|
||||
|
||||
replserver.emit('line', 'process.nextTick(() => { throw null; })');
|
||||
replserver.emit('line', '.exit');
|
||||
replServer.emit('line', 'process.nextTick(() => { throw null; })');
|
||||
replServer.emit('line', '.exit');
|
||||
|
||||
setTimeout(() => {
|
||||
assert(text.includes('Uncaught null'));
|
||||
assert(output.accumulator.includes('Uncaught null'));
|
||||
}, 0);
|
||||
|
|
|
|||
|
|
@ -1,36 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const repl = require('repl');
|
||||
const stream = require('stream');
|
||||
const assert = require('assert');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
// Pasting big input should not cause the process to have a huge CPU usage.
|
||||
|
||||
const cpuUsage = process.cpuUsage();
|
||||
|
||||
const r = initRepl();
|
||||
r.input.emit('data', 'a'.repeat(2e4) + '\n');
|
||||
r.input.emit('data', '.exit\n');
|
||||
const { replServer } = startNewREPLServer({}, { disableDomainErrorAssert: true });
|
||||
replServer.input.emit('data', 'a'.repeat(2e4) + '\n');
|
||||
replServer.input.emit('data', '.exit\n');
|
||||
|
||||
r.once('exit', common.mustCall(() => {
|
||||
replServer.once('exit', common.mustCall(() => {
|
||||
const diff = process.cpuUsage(cpuUsage);
|
||||
assert.ok(diff.user < 1e6);
|
||||
}));
|
||||
|
||||
function initRepl() {
|
||||
const input = new stream();
|
||||
input.write = input.pause = input.resume = () => {};
|
||||
input.readable = true;
|
||||
|
||||
const output = new stream();
|
||||
output.write = () => {};
|
||||
output.writable = true;
|
||||
|
||||
return repl.start({
|
||||
input,
|
||||
output,
|
||||
terminal: true,
|
||||
prompt: ''
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,32 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const stackRegExp = /(REPL\d+):[0-9]+:[0-9]+/g;
|
||||
|
||||
function run({ command, expected }) {
|
||||
let accum = '';
|
||||
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
|
||||
outputStream.write = (data) => accum += data.replace('\r', '');
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
terminal: false,
|
||||
useColors: false
|
||||
}, {
|
||||
disableDomainErrorAssert: true,
|
||||
});
|
||||
|
||||
r.write(`${command}\n`);
|
||||
replServer.write(`${command}\n`);
|
||||
if (typeof expected === 'string') {
|
||||
assert.strictEqual(
|
||||
accum.replace(stackRegExp, '$1:*:*'),
|
||||
output.accumulator.replace(stackRegExp, '$1:*:*'),
|
||||
expected.replace(stackRegExp, '$1:*:*')
|
||||
);
|
||||
} else {
|
||||
assert.match(
|
||||
accum.replace(stackRegExp, '$1:*:*'),
|
||||
output.accumulator.replace(stackRegExp, '$1:*:*'),
|
||||
expected
|
||||
);
|
||||
}
|
||||
r.close();
|
||||
replServer.close();
|
||||
}
|
||||
|
||||
const origPrepareStackTrace = Error.prepareStackTrace;
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const { PassThrough } = require('stream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
{
|
||||
const input = new PassThrough();
|
||||
const output = new PassThrough();
|
||||
const testingReplPrompt = '_REPL_TESTING_PROMPT_>';
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output,
|
||||
writer: String,
|
||||
terminal: false,
|
||||
useColors: false
|
||||
});
|
||||
const { replServer, output } = startNewREPLServer(
|
||||
{ prompt: testingReplPrompt },
|
||||
{ disableDomainErrorAssert: true }
|
||||
);
|
||||
|
||||
r.write('throw new Error("foo[a]")\n');
|
||||
r.close();
|
||||
assert.strictEqual(output.read().toString(), 'Uncaught Error: foo[a]\n');
|
||||
}
|
||||
replServer.write('throw new Error("foo[a]")\n');
|
||||
|
||||
assert.strictEqual(
|
||||
output.accumulator.split('\n').filter((line) => !line.includes(testingReplPrompt)).join(''),
|
||||
'Uncaught Error: foo[a]'
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,43 +1,34 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const stackRegExp = /(at .*REPL\d+:)[0-9]+:[0-9]+/g;
|
||||
|
||||
function run({ command, expected, ...extraREPLOptions }, i) {
|
||||
let accum = '';
|
||||
const { replServer, output } = startNewREPLServer(
|
||||
{
|
||||
terminal: false,
|
||||
useColors: false,
|
||||
...extraREPLOptions
|
||||
},
|
||||
{ disableDomainErrorAssert: true }
|
||||
);
|
||||
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
|
||||
outputStream.write = (data) => accum += data.replace('\r', '');
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
terminal: false,
|
||||
useColors: false,
|
||||
...extraREPLOptions
|
||||
});
|
||||
|
||||
r.write(`${command}\n`);
|
||||
console.log(i);
|
||||
replServer.write(`${command}\n`);
|
||||
if (typeof expected === 'string') {
|
||||
assert.strictEqual(
|
||||
accum.replace(stackRegExp, '$1*:*'),
|
||||
output.accumulator.replace(stackRegExp, '$1*:*'),
|
||||
expected.replace(stackRegExp, '$1*:*')
|
||||
);
|
||||
} else {
|
||||
assert.match(
|
||||
accum.replace(stackRegExp, '$1*:*'),
|
||||
output.accumulator.replace(stackRegExp, '$1*:*'),
|
||||
expected
|
||||
);
|
||||
}
|
||||
r.close();
|
||||
replServer.close();
|
||||
}
|
||||
|
||||
const tests = [
|
||||
|
|
|
|||
|
|
@ -1,29 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
common.skipIfInspectorDisabled();
|
||||
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
repl.start({
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
useGlobal: false,
|
||||
terminal: true,
|
||||
useColors: true
|
||||
});
|
||||
const { input, output } = startNewREPLServer(
|
||||
{ useColors: true }, { disableDomainErrorAssert: true }
|
||||
);
|
||||
|
||||
let output = '';
|
||||
outputStream.write = (chunk) => output += chunk;
|
||||
output.accumulator = '';
|
||||
|
||||
for (const char of ['\\n', '\\v', '\\r']) {
|
||||
inputStream.emit('data', `"${char}"()`);
|
||||
input.emit('data', `"${char}"()`);
|
||||
// Make sure the output is on a single line
|
||||
assert.strictEqual(output, `"${char}"()\n\x1B[90mTypeError: "\x1B[39m\x1B[9G\x1B[1A`);
|
||||
inputStream.run(['']);
|
||||
output = '';
|
||||
assert.strictEqual(output.accumulator, `"${char}"()\n\x1B[90mTypeError: "\x1B[39m\x1B[7G\x1B[1A`);
|
||||
input.run(['']);
|
||||
output.accumulator = '';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
common.skipIfInspectorDisabled();
|
||||
|
||||
const inputStream = new ArrayStream();
|
||||
const outputStream = new ArrayStream();
|
||||
repl.start({
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
useGlobal: false,
|
||||
terminal: true,
|
||||
useColors: true
|
||||
});
|
||||
const { output, input } = startNewREPLServer();
|
||||
|
||||
let output = '';
|
||||
outputStream.write = (chunk) => output += chunk;
|
||||
output.accumulator = '';
|
||||
|
||||
// Input without '\n' triggering actual run.
|
||||
const input = 'while (true) {}';
|
||||
inputStream.emit('data', input);
|
||||
const inputStr = 'while (true) {}';
|
||||
input.emit('data', inputStr);
|
||||
// No preview available when timed out.
|
||||
assert.strictEqual(output, input);
|
||||
assert.strictEqual(output.accumulator, inputStr);
|
||||
|
|
|
|||
|
|
@ -21,27 +21,19 @@
|
|||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const util = require('util');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
common.allowGlobals(42);
|
||||
|
||||
// Create a dummy stream that does nothing
|
||||
const dummy = new ArrayStream();
|
||||
|
||||
function testReset(cb) {
|
||||
const r = repl.start({
|
||||
input: dummy,
|
||||
output: dummy,
|
||||
useGlobal: false
|
||||
});
|
||||
r.context.foo = 42;
|
||||
r.on('reset', common.mustCall(function(context) {
|
||||
const { replServer } = startNewREPLServer();
|
||||
replServer.context.foo = 42;
|
||||
replServer.on('reset', common.mustCall(function(context) {
|
||||
assert(!!context, 'REPL did not emit a context with reset event');
|
||||
assert.strictEqual(context, r.context, 'REPL emitted incorrect context. ' +
|
||||
`context is ${util.inspect(context)}, expected ${util.inspect(r.context)}`);
|
||||
assert.strictEqual(context, replServer.context, 'REPL emitted incorrect context. ' +
|
||||
`context is ${util.inspect(context)}, expected ${util.inspect(replServer.context)}`);
|
||||
assert.strictEqual(
|
||||
context.foo,
|
||||
undefined,
|
||||
|
|
@ -51,17 +43,13 @@ function testReset(cb) {
|
|||
context.foo = 42;
|
||||
cb();
|
||||
}));
|
||||
r.resetContext();
|
||||
replServer.resetContext();
|
||||
}
|
||||
|
||||
function testResetGlobal() {
|
||||
const r = repl.start({
|
||||
input: dummy,
|
||||
output: dummy,
|
||||
useGlobal: true
|
||||
});
|
||||
r.context.foo = 42;
|
||||
r.on('reset', common.mustCall(function(context) {
|
||||
const { replServer } = startNewREPLServer({ useGlobal: true });
|
||||
replServer.context.foo = 42;
|
||||
replServer.on('reset', common.mustCall(function(context) {
|
||||
assert.strictEqual(
|
||||
context.foo,
|
||||
42,
|
||||
|
|
@ -69,7 +57,7 @@ function testResetGlobal() {
|
|||
`context.foo is ${context.foo}, expected 42.`
|
||||
);
|
||||
}));
|
||||
r.resetContext();
|
||||
replServer.resetContext();
|
||||
}
|
||||
|
||||
testReset(common.mustCall(testResetGlobal));
|
||||
|
|
|
|||
|
|
@ -1,30 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const assert = require('node:assert');
|
||||
const fs = require('node:fs');
|
||||
const repl = require('node:repl');
|
||||
const path = require('node:path');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Test for saving a REPL session in editor mode
|
||||
|
||||
const input = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output: new ArrayStream(),
|
||||
allowBlockingCompletions: true,
|
||||
terminal: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['.editor']);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const assert = require('node:assert');
|
||||
const repl = require('node:repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Test for the appropriate handling of cases in which REPL saves fail
|
||||
|
||||
const input = new ArrayStream();
|
||||
const output = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input, output } = startNewREPLServer({ terminal: false });
|
||||
|
||||
// NUL (\0) is disallowed in filenames in UNIX-like operating systems and
|
||||
// Windows so we can use that to test failed saves.
|
||||
|
|
|
|||
|
|
@ -1,28 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('node:assert');
|
||||
const repl = require('node:repl');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Tests that an appropriate error is displayed if the user tries to load a directory instead of a file
|
||||
|
||||
const input = new ArrayStream();
|
||||
const output = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input, output } = startNewREPLServer({ terminal: false });
|
||||
|
||||
const dirPath = tmpdir.path;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('node:assert');
|
||||
const repl = require('node:repl');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Tests that an appropriate error is displayed if the user tries to load a non existent file
|
||||
|
||||
const input = new ArrayStream();
|
||||
const output = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input, output } = startNewREPLServer({ terminal: false });
|
||||
|
||||
const filePath = tmpdir.resolve('file.does.not.exist');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('node:assert');
|
||||
const repl = require('node:repl');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Tests that an appropriate error is displayed if .load is called without a filename
|
||||
|
||||
const input = new ArrayStream();
|
||||
const output = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input, output } = startNewREPLServer({ terminal: false });
|
||||
|
||||
output.write = common.mustCall(function(data) {
|
||||
assert.strictEqual(data, 'The "file" argument must be specified\n');
|
||||
|
|
|
|||
|
|
@ -1,28 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('node:assert');
|
||||
const repl = require('node:repl');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
// Tests that an appropriate error is displayed if .save is called without a filename
|
||||
|
||||
const input = new ArrayStream();
|
||||
const output = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input, output } = startNewREPLServer({ terminal: false });
|
||||
|
||||
output.write = common.mustCall(function(data) {
|
||||
assert.strictEqual(data, 'The "file" argument must be specified\n');
|
||||
|
|
|
|||
|
|
@ -22,11 +22,9 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const assert = require('node:assert');
|
||||
const fs = require('node:fs');
|
||||
const repl = require('node:repl');
|
||||
const path = require('node:path');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
|
|
@ -34,17 +32,7 @@ tmpdir.refresh();
|
|||
|
||||
// Tests that a REPL session data can be saved to and loaded from a file
|
||||
|
||||
const input = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output: new ArrayStream(),
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input } = startNewREPLServer({ terminal: false });
|
||||
|
||||
const filePath = path.resolve(tmpdir.path, 'test.save.js');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
let found = false;
|
||||
|
||||
process.on('exit', () => {
|
||||
assert.strictEqual(found, true);
|
||||
});
|
||||
|
||||
ArrayStream.prototype.write = function(output) {
|
||||
const { input, output } = startNewREPLServer({}, { disableDomainErrorAssert: true });
|
||||
|
||||
output.write = (data) => {
|
||||
// Matching only on a minimal piece of the stack because the string will vary
|
||||
// greatly depending on the JavaScript engine. V8 includes `;` because it
|
||||
// displays the line of code (`var foo bar;`) that is causing a problem.
|
||||
// ChakraCore does not display the line of code but includes `;` in the phrase
|
||||
// `Expected ';' `.
|
||||
if (/;/.test(output))
|
||||
if (/;/.test(data))
|
||||
found = true;
|
||||
};
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
repl.start('', putIn);
|
||||
let file = fixtures.path('syntax', 'bad_syntax');
|
||||
|
||||
if (common.isWindows)
|
||||
file = file.replace(/\\/g, '\\\\');
|
||||
|
||||
putIn.run(['.clear']);
|
||||
putIn.run([`require('${file}');`]);
|
||||
input.run(['.clear']);
|
||||
input.run([`require('${file}');`]);
|
||||
|
|
|
|||
|
|
@ -1,22 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { hijackStderr, restoreStderr } = require('../common/hijackstdio');
|
||||
const assert = require('assert');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const repl = require('repl');
|
||||
|
||||
const input = new ArrayStream();
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output: process.stdout,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
for (const type of [
|
||||
Array,
|
||||
|
|
|
|||
|
|
@ -1,27 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const { describe, it, before, after } = require('node:test');
|
||||
const assert = require('assert');
|
||||
|
||||
const repl = require('repl');
|
||||
|
||||
function prepareREPL() {
|
||||
const input = new ArrayStream();
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output: process.stdout,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
|
||||
return { replServer, input };
|
||||
}
|
||||
|
||||
function testCompletion(replServer, { input, expectedCompletions }) {
|
||||
replServer.complete(
|
||||
input,
|
||||
|
|
@ -36,7 +19,7 @@ describe('REPL tab object completion on computed properties', () => {
|
|||
let replServer;
|
||||
|
||||
before(() => {
|
||||
const { replServer: server, input } = prepareREPL();
|
||||
const { replServer: server, input } = startNewREPLServer();
|
||||
replServer = server;
|
||||
|
||||
input.run([
|
||||
|
|
@ -97,7 +80,7 @@ describe('REPL tab object completion on computed properties', () => {
|
|||
let replServer;
|
||||
|
||||
before(() => {
|
||||
const { replServer: server, input } = prepareREPL();
|
||||
const { replServer: server, input } = startNewREPLServer();
|
||||
replServer = server;
|
||||
|
||||
input.run([
|
||||
|
|
|
|||
|
|
@ -1,28 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
ArrayStream.prototype.write = () => {};
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
const testMe = repl.start('', putIn);
|
||||
const { replServer, input } = startNewREPLServer({}, { disableDomainErrorAssert: true });
|
||||
|
||||
// https://github.com/nodejs/node/issues/3346
|
||||
// Tab-completion should be empty
|
||||
putIn.run(['.clear']);
|
||||
putIn.run(['function () {']);
|
||||
testMe.complete('arguments.', common.mustCall((err, completions) => {
|
||||
input.run(['.clear', 'function () {']);
|
||||
replServer.complete('arguments.', common.mustCall((err, completions) => {
|
||||
assert.strictEqual(err, null);
|
||||
assert.deepStrictEqual(completions, [[], 'arguments.']);
|
||||
}));
|
||||
|
||||
putIn.run(['.clear']);
|
||||
putIn.run(['function () {']);
|
||||
putIn.run(['undef;']);
|
||||
testMe.complete('undef.', common.mustCall((err, completions) => {
|
||||
input.run(['.clear', 'function () {', 'undef;']);
|
||||
replServer.complete('undef.', common.mustCall((err, completions) => {
|
||||
assert.strictEqual(err, null);
|
||||
assert.deepStrictEqual(completions, [[], 'undef.']);
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,21 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
|
||||
const repl = require('repl');
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
// To test custom completer function.
|
||||
// Sync mode.
|
||||
{
|
||||
const customCompletions = 'aaa aa1 aa2 bbb bb1 bb2 bb3 ccc ddd eee'.split(' ');
|
||||
const testCustomCompleterSyncMode = repl.start({
|
||||
prompt: '',
|
||||
input: putIn,
|
||||
output: putIn,
|
||||
const { replServer } = startNewREPLServer({
|
||||
completer: function completer(line) {
|
||||
const hits = customCompletions.filter((c) => c.startsWith(line));
|
||||
// Show all completions if none found.
|
||||
|
|
@ -25,7 +18,7 @@ const putIn = new ArrayStream();
|
|||
|
||||
// On empty line should output all the custom completions
|
||||
// without complete anything.
|
||||
testCustomCompleterSyncMode.complete('', common.mustCall((error, data) => {
|
||||
replServer.complete('', common.mustCall((error, data) => {
|
||||
assert.deepStrictEqual(data, [
|
||||
customCompletions,
|
||||
'',
|
||||
|
|
@ -33,7 +26,7 @@ const putIn = new ArrayStream();
|
|||
}));
|
||||
|
||||
// On `a` should output `aaa aa1 aa2` and complete until `aa`.
|
||||
testCustomCompleterSyncMode.complete('a', common.mustCall((error, data) => {
|
||||
replServer.complete('a', common.mustCall((error, data) => {
|
||||
assert.deepStrictEqual(data, [
|
||||
'aaa aa1 aa2'.split(' '),
|
||||
'a',
|
||||
|
|
@ -45,10 +38,7 @@ const putIn = new ArrayStream();
|
|||
// Async mode.
|
||||
{
|
||||
const customCompletions = 'aaa aa1 aa2 bbb bb1 bb2 bb3 ccc ddd eee'.split(' ');
|
||||
const testCustomCompleterAsyncMode = repl.start({
|
||||
prompt: '',
|
||||
input: putIn,
|
||||
output: putIn,
|
||||
const { replServer } = startNewREPLServer({
|
||||
completer: function completer(line, callback) {
|
||||
const hits = customCompletions.filter((c) => c.startsWith(line));
|
||||
// Show all completions if none found.
|
||||
|
|
@ -58,7 +48,7 @@ const putIn = new ArrayStream();
|
|||
|
||||
// On empty line should output all the custom completions
|
||||
// without complete anything.
|
||||
testCustomCompleterAsyncMode.complete('', common.mustCall((error, data) => {
|
||||
replServer.complete('', common.mustCall((error, data) => {
|
||||
assert.deepStrictEqual(data, [
|
||||
customCompletions,
|
||||
'',
|
||||
|
|
@ -66,7 +56,7 @@ const putIn = new ArrayStream();
|
|||
}));
|
||||
|
||||
// On `a` should output `aaa aa1 aa2` and complete until `aa`.
|
||||
testCustomCompleterAsyncMode.complete('a', common.mustCall((error, data) => {
|
||||
replServer.complete('a', common.mustCall((error, data) => {
|
||||
assert.deepStrictEqual(data, [
|
||||
'aaa aa1 aa2'.split(' '),
|
||||
'a',
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const { isMainThread } = require('worker_threads');
|
||||
|
||||
|
|
@ -11,17 +11,7 @@ if (!isMainThread) {
|
|||
common.skip('process.chdir is not available in Workers');
|
||||
}
|
||||
|
||||
const repl = require('repl');
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input: new ArrayStream(),
|
||||
output: process.stdout,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
// Tab completion for files/directories
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,29 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const repl = require('repl');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
(async function() {
|
||||
await runTest();
|
||||
})().then(common.mustCall());
|
||||
|
||||
async function runTest() {
|
||||
const input = new ArrayStream();
|
||||
const output = new ArrayStream();
|
||||
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output: output,
|
||||
allowBlockingCompletions: true,
|
||||
terminal: true
|
||||
});
|
||||
|
||||
replServer._domain.on('error', (e) => {
|
||||
assert.fail(`Error in REPL domain: ${e}`);
|
||||
});
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
replServer.eval(`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const { builtinModules } = require('module');
|
||||
|
|
@ -19,20 +18,12 @@ if (!isMainThread) {
|
|||
process.chdir(fixtures.fixturesDir);
|
||||
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
const testMe = repl.start({
|
||||
prompt: '',
|
||||
input: putIn,
|
||||
output: process.stdout,
|
||||
allowBlockingCompletions: true
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
testMe._domain.on('error', assert.ifError);
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
// Tab complete provides built in libs for import()
|
||||
testMe.complete('import(\'', common.mustSucceed((data) => {
|
||||
replServer.complete('import(\'', common.mustSucceed((data) => {
|
||||
publicUnprefixedModules.forEach((lib) => {
|
||||
assert(
|
||||
data[0].includes(lib) && data[0].includes(`node:${lib}`),
|
||||
|
|
@ -42,14 +33,14 @@ testMe.complete('import(\'', common.mustSucceed((data) => {
|
|||
const newModule = 'foobar';
|
||||
assert(!builtinModules.includes(newModule));
|
||||
repl.builtinModules.push(newModule);
|
||||
testMe.complete('import(\'', common.mustSucceed(([modules]) => {
|
||||
replServer.complete('import(\'', common.mustSucceed(([modules]) => {
|
||||
assert.strictEqual(data[0].length + 1, modules.length);
|
||||
assert(modules.includes(newModule) &&
|
||||
!modules.includes(`node:${newModule}`));
|
||||
}));
|
||||
}));
|
||||
|
||||
testMe.complete("import\t( 'n", common.mustSucceed((data) => {
|
||||
replServer.complete("import\t( 'n", common.mustSucceed((data) => {
|
||||
assert.strictEqual(data.length, 2);
|
||||
assert.strictEqual(data[1], 'n');
|
||||
const completions = data[0];
|
||||
|
|
@ -74,38 +65,37 @@ testMe.complete("import\t( 'n", common.mustSucceed((data) => {
|
|||
const expected = ['@nodejsscope', '@nodejsscope/'];
|
||||
// Import calls should handle all types of quotation marks.
|
||||
for (const quotationMark of ["'", '"', '`']) {
|
||||
putIn.run(['.clear']);
|
||||
testMe.complete('import(`@nodejs', common.mustSucceed((data) => {
|
||||
input.run(['.clear']);
|
||||
replServer.complete('import(`@nodejs', common.mustSucceed((data) => {
|
||||
assert.deepStrictEqual(data, [expected, '@nodejs']);
|
||||
}));
|
||||
|
||||
putIn.run(['.clear']);
|
||||
input.run(['.clear']);
|
||||
// Completions should not be greedy in case the quotation ends.
|
||||
const input = `import(${quotationMark}@nodejsscope${quotationMark}`;
|
||||
testMe.complete(input, common.mustSucceed((data) => {
|
||||
replServer.complete(`import(${quotationMark}@nodejsscope${quotationMark}`, common.mustSucceed((data) => {
|
||||
assert.deepStrictEqual(data, [[], undefined]);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
putIn.run(['.clear']);
|
||||
input.run(['.clear']);
|
||||
// Completions should find modules and handle whitespace after the opening
|
||||
// bracket.
|
||||
testMe.complete('import \t("no_ind', common.mustSucceed((data) => {
|
||||
replServer.complete('import \t("no_ind', common.mustSucceed((data) => {
|
||||
assert.deepStrictEqual(data, [['no_index', 'no_index/'], 'no_ind']);
|
||||
}));
|
||||
}
|
||||
|
||||
// Test tab completion for import() relative to the current directory
|
||||
{
|
||||
putIn.run(['.clear']);
|
||||
input.run(['.clear']);
|
||||
|
||||
const cwd = process.cwd();
|
||||
process.chdir(__dirname);
|
||||
|
||||
['import(\'.', 'import(".'].forEach((input) => {
|
||||
testMe.complete(input, common.mustSucceed((data) => {
|
||||
replServer.complete(input, common.mustSucceed((data) => {
|
||||
assert.strictEqual(data.length, 2);
|
||||
assert.strictEqual(data[1], '.');
|
||||
assert.strictEqual(data[0].length, 2);
|
||||
|
|
@ -115,14 +105,14 @@ testMe.complete("import\t( 'n", common.mustSucceed((data) => {
|
|||
});
|
||||
|
||||
['import(\'..', 'import("..'].forEach((input) => {
|
||||
testMe.complete(input, common.mustSucceed((data) => {
|
||||
replServer.complete(input, common.mustSucceed((data) => {
|
||||
assert.deepStrictEqual(data, [['../'], '..']);
|
||||
}));
|
||||
});
|
||||
|
||||
['./', './test-'].forEach((path) => {
|
||||
[`import('${path}`, `import("${path}`].forEach((input) => {
|
||||
testMe.complete(input, common.mustSucceed((data) => {
|
||||
replServer.complete(input, common.mustSucceed((data) => {
|
||||
assert.strictEqual(data.length, 2);
|
||||
assert.strictEqual(data[1], path);
|
||||
assert.ok(data[0].includes('./test-repl-tab-complete.js'));
|
||||
|
|
@ -132,7 +122,7 @@ testMe.complete("import\t( 'n", common.mustSucceed((data) => {
|
|||
|
||||
['../parallel/', '../parallel/test-'].forEach((path) => {
|
||||
[`import('${path}`, `import("${path}`].forEach((input) => {
|
||||
testMe.complete(input, common.mustSucceed((data) => {
|
||||
replServer.complete(input, common.mustSucceed((data) => {
|
||||
assert.strictEqual(data.length, 2);
|
||||
assert.strictEqual(data[1], path);
|
||||
assert.ok(data[0].includes('../parallel/test-repl-tab-complete.js'));
|
||||
|
|
@ -142,7 +132,7 @@ testMe.complete("import\t( 'n", common.mustSucceed((data) => {
|
|||
|
||||
{
|
||||
const path = '../fixtures/repl-folder-extensions/f';
|
||||
testMe.complete(`import('${path}`, common.mustSucceed((data) => {
|
||||
replServer.complete(`import('${path}`, common.mustSucceed((data) => {
|
||||
assert.strictEqual(data.length, 2);
|
||||
assert.strictEqual(data[1], path);
|
||||
assert.ok(data[0].includes(
|
||||
|
|
|
|||
|
|
@ -1,21 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const DEFAULT_MAX_LISTENERS = require('events').defaultMaxListeners;
|
||||
|
||||
ArrayStream.prototype.write = () => {};
|
||||
|
||||
const putIn = new ArrayStream();
|
||||
const testMe = repl.start('', putIn);
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
// https://github.com/nodejs/node/issues/18284
|
||||
// Tab-completion should not repeatedly add the
|
||||
// `Runtime.executionContextCreated` listener
|
||||
process.on('warning', common.mustNotCall());
|
||||
|
||||
putIn.run(['async function test() {']);
|
||||
input.run(['async function test() {']);
|
||||
for (let i = 0; i < DEFAULT_MAX_LISTENERS; i++) {
|
||||
testMe.complete('await Promise.resolve()', () => {});
|
||||
replServer.complete('await Promise.resolve()', () => {});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { describe, it } = require('node:test');
|
||||
const assert = require('assert');
|
||||
|
||||
const repl = require('repl');
|
||||
|
||||
function prepareREPL() {
|
||||
const input = new ArrayStream();
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output: process.stdout,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
|
||||
return { replServer, input };
|
||||
}
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
function getNoResultsFunction() {
|
||||
return common.mustSucceed((data) => {
|
||||
|
|
@ -44,7 +27,7 @@ describe('REPL tab completion without side effects', () => {
|
|||
'arr[incCounter()].b',
|
||||
]) {
|
||||
it(`does not evaluate with side effects (${code})`, async () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
input.run(setup);
|
||||
|
||||
replServer.complete(code, getNoResultsFunction());
|
||||
|
|
|
|||
|
|
@ -2,41 +2,28 @@
|
|||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
// Tab completion in editor mode
|
||||
{
|
||||
const editorStream = new ArrayStream();
|
||||
const editor = repl.start({
|
||||
stream: editorStream,
|
||||
terminal: true,
|
||||
useColors: false
|
||||
});
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
editorStream.run(['.clear']);
|
||||
editorStream.run(['.editor']);
|
||||
input.run(['.clear', '.editor']);
|
||||
|
||||
editor.completer('Uin', common.mustCall((_error, data) => {
|
||||
replServer.completer('Uin', common.mustCall((_error, data) => {
|
||||
assert.deepStrictEqual(data, [['Uint'], 'Uin']);
|
||||
}));
|
||||
|
||||
editorStream.run(['.clear']);
|
||||
editorStream.run(['.editor']);
|
||||
input.run(['.clear', '.editor']);
|
||||
|
||||
editor.completer('var log = console.l', common.mustCall((_error, data) => {
|
||||
replServer.completer('var log = console.l', common.mustCall((_error, data) => {
|
||||
assert.deepStrictEqual(data, [['console.log'], 'console.l']);
|
||||
}));
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/nodejs/node/issues/43528
|
||||
{
|
||||
const stream = new ArrayStream();
|
||||
const replServer = repl.start({
|
||||
input: stream,
|
||||
output: stream,
|
||||
terminal: true,
|
||||
});
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
// Editor mode
|
||||
replServer.write('.editor\n');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { builtinModules } = require('module');
|
||||
|
|
@ -19,24 +18,11 @@ if (!isMainThread) {
|
|||
process.chdir(fixtures.fixturesDir);
|
||||
|
||||
const repl = require('repl');
|
||||
|
||||
function prepareREPL() {
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input: new ArrayStream(),
|
||||
output: process.stdout,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
|
||||
return replServer;
|
||||
}
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
// Tab completion on require on builtin modules works
|
||||
{
|
||||
const replServer = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
"require('",
|
||||
|
|
@ -65,7 +51,7 @@ function prepareREPL() {
|
|||
|
||||
// Tab completion on require on builtin modules works (with extra spaces and "n" prefix)
|
||||
{
|
||||
const replServer = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
"require\t( 'n",
|
||||
|
|
@ -98,7 +84,7 @@ function prepareREPL() {
|
|||
{
|
||||
const expected = ['@nodejsscope', '@nodejsscope/'];
|
||||
|
||||
const replServer = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
// Require calls should handle all types of quotation marks.
|
||||
for (const quotationMark of ["'", '"', '`']) {
|
||||
|
|
@ -124,7 +110,7 @@ function prepareREPL() {
|
|||
|
||||
{
|
||||
// Completions should find modules and handle whitespace after the opening bracket.
|
||||
const replServer = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
'require \t("no_ind',
|
||||
|
|
@ -137,7 +123,7 @@ function prepareREPL() {
|
|||
|
||||
// Test tab completion for require() relative to the current directory
|
||||
{
|
||||
const replServer = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
const cwd = process.cwd();
|
||||
process.chdir(__dirname);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
// This test verifies that tab completion works correctly with unary expressions
|
||||
|
|
@ -12,25 +12,20 @@ const { describe, it } = require('node:test');
|
|||
|
||||
describe('REPL tab completion with unary expressions', () => {
|
||||
it('should handle delete operator correctly', (t, done) => {
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
terminal: false,
|
||||
});
|
||||
const { replServer } = startNewREPLServer({ terminal: false });
|
||||
|
||||
// Test delete with member expression
|
||||
r.complete(
|
||||
replServer.complete(
|
||||
'delete globalThis._',
|
||||
common.mustSucceed((completions) => {
|
||||
assert.strictEqual(completions[1], 'globalThis._');
|
||||
|
||||
// Test delete with identifier
|
||||
r.complete(
|
||||
replServer.complete(
|
||||
'delete globalThis',
|
||||
common.mustSucceed((completions) => {
|
||||
assert.strictEqual(completions[1], 'globalThis');
|
||||
r.close();
|
||||
replServer.close();
|
||||
done();
|
||||
})
|
||||
);
|
||||
|
|
@ -39,48 +34,33 @@ describe('REPL tab completion with unary expressions', () => {
|
|||
});
|
||||
|
||||
it('should handle typeof operator correctly', (t, done) => {
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
terminal: false,
|
||||
});
|
||||
const { replServer } = startNewREPLServer({ terminal: false });
|
||||
|
||||
r.complete(
|
||||
replServer.complete(
|
||||
'typeof globalThis',
|
||||
common.mustSucceed((completions) => {
|
||||
assert.strictEqual(completions[1], 'globalThis');
|
||||
r.close();
|
||||
replServer.close();
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle void operator correctly', (t, done) => {
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
terminal: false,
|
||||
});
|
||||
const { replServer } = startNewREPLServer({ terminal: false });
|
||||
|
||||
r.complete(
|
||||
replServer.complete(
|
||||
'void globalThis',
|
||||
common.mustSucceed((completions) => {
|
||||
assert.strictEqual(completions[1], 'globalThis');
|
||||
r.close();
|
||||
replServer.close();
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle other unary operators correctly', (t, done) => {
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
terminal: false,
|
||||
});
|
||||
const { replServer } = startNewREPLServer({ terminal: false });
|
||||
|
||||
const unaryOperators = [
|
||||
'!globalThis',
|
||||
|
|
@ -93,13 +73,13 @@ describe('REPL tab completion with unary expressions', () => {
|
|||
|
||||
function testNext() {
|
||||
if (testIndex >= unaryOperators.length) {
|
||||
r.close();
|
||||
replServer.close();
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
const testCase = unaryOperators[testIndex++];
|
||||
r.complete(
|
||||
replServer.complete(
|
||||
testCase,
|
||||
common.mustSucceed((completions) => {
|
||||
assert.strictEqual(completions[1], 'globalThis');
|
||||
|
|
@ -112,26 +92,21 @@ describe('REPL tab completion with unary expressions', () => {
|
|||
});
|
||||
|
||||
it('should still evaluate globalThis correctly after unary expression completion', (t, done) => {
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
terminal: false,
|
||||
});
|
||||
const { replServer } = startNewREPLServer({ terminal: false });
|
||||
|
||||
// First trigger completion with delete
|
||||
r.complete(
|
||||
replServer.complete(
|
||||
'delete globalThis._',
|
||||
common.mustSucceed(() => {
|
||||
// Then evaluate globalThis
|
||||
r.eval(
|
||||
replServer.eval(
|
||||
'globalThis',
|
||||
r.context,
|
||||
replServer.context,
|
||||
'test.js',
|
||||
common.mustSucceed((result) => {
|
||||
assert.strictEqual(typeof result, 'object');
|
||||
assert.ok(result !== null);
|
||||
r.close();
|
||||
replServer.close();
|
||||
done();
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -22,42 +22,25 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
const { describe, it } = require('node:test');
|
||||
const assert = require('assert');
|
||||
|
||||
const repl = require('repl');
|
||||
|
||||
function getNoResultsFunction() {
|
||||
return common.mustSucceed((data) => {
|
||||
assert.deepStrictEqual(data[0], []);
|
||||
});
|
||||
}
|
||||
|
||||
function prepareREPL() {
|
||||
const input = new ArrayStream();
|
||||
const replServer = repl.start({
|
||||
prompt: '',
|
||||
input,
|
||||
output: process.stdout,
|
||||
allowBlockingCompletions: true,
|
||||
});
|
||||
|
||||
// Some errors are passed to the domain, but do not callback
|
||||
replServer._domain.on('error', assert.ifError);
|
||||
|
||||
return { replServer, input };
|
||||
}
|
||||
|
||||
describe('REPL tab completion (core functionality)', () => {
|
||||
it('does not break with variable declarations without an initialization', () => {
|
||||
const { replServer } = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
replServer.complete('let a', getNoResultsFunction());
|
||||
replServer.close();
|
||||
});
|
||||
|
||||
it('does not break in an object literal', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var inner = {', 'one:1']);
|
||||
|
||||
|
|
@ -74,7 +57,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works with optional chaining', () => {
|
||||
const { replServer } = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
'console?.lo',
|
||||
|
|
@ -102,7 +85,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('returns object completions', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var inner = {', 'one:1']);
|
||||
|
||||
|
|
@ -119,7 +102,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('does not break in a ternary operator with ()', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var inner = ( true ', '?', '{one: 1} : ']);
|
||||
|
||||
|
|
@ -129,7 +112,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works on literals', () => {
|
||||
const { replServer } = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
'``.a',
|
||||
|
|
@ -172,7 +155,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it("does not return a function's local variable", () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var top = function() {', 'var inner = {one:1};', '}']);
|
||||
|
||||
|
|
@ -182,7 +165,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it("does not return a function's local variable even when the function has parameters", () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'var top = function(one, two) {',
|
||||
|
|
@ -198,7 +181,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
|
||||
it("does not return a function's local variable" +
|
||||
'even if the scope is nested inside an immediately executed function', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'var top = function() {',
|
||||
|
|
@ -216,7 +199,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
it("does not return a function's local variable" +
|
||||
'even if the scope is nested inside an immediately executed function' +
|
||||
'(the definition has the params and { on a separate line)', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'var top = function() {',
|
||||
|
|
@ -233,7 +216,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('currently does not work, but should not break (local inner)', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'var top = function() {',
|
||||
|
|
@ -250,7 +233,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('currently does not work, but should not break (local inner parens next line)', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'var top = function() {',
|
||||
|
|
@ -268,7 +251,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works on non-Objects', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var str = "test";']);
|
||||
|
||||
|
|
@ -283,7 +266,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('should be case-insensitive if member part is lower-case', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var foo = { barBar: 1, BARbuz: 2, barBLA: 3 };']);
|
||||
|
||||
|
|
@ -301,7 +284,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('should be case-insensitive if member part is upper-case', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var foo = { barBar: 1, BARbuz: 2, barBLA: 3 };']);
|
||||
|
||||
|
|
@ -319,7 +302,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('should not break on spaces', () => {
|
||||
const { replServer } = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
const spaceTimeout = setTimeout(function() {
|
||||
throw new Error('timeout');
|
||||
|
|
@ -338,7 +321,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it(`should pick up the global "toString" object, and any other properties up the "global" object's prototype chain`, () => {
|
||||
const { replServer } = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
'toSt',
|
||||
|
|
@ -351,7 +334,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('should make own properties shadow properties on the prototype', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'var x = Object.create(null);',
|
||||
|
|
@ -373,7 +356,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works on context properties', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var custom = "test";']);
|
||||
|
||||
|
|
@ -388,7 +371,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it("doesn't crash REPL with half-baked proxy objects", () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'var proxy = new Proxy({}, {ownKeys: () => { throw new Error(); }});',
|
||||
|
|
@ -406,7 +389,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('does not include integer members of an Array', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var ary = [1,2,3];']);
|
||||
|
||||
|
|
@ -423,7 +406,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('does not include integer keys in an object', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var obj = {1:"a","1a":"b",a:"b"};']);
|
||||
|
||||
|
|
@ -440,7 +423,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('does not try to complete results of non-simple expressions', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['function a() {}']);
|
||||
|
||||
|
|
@ -450,7 +433,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works when prefixed with spaces', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var obj = {1:"a","1a":"b",a:"b"};']);
|
||||
|
||||
|
|
@ -467,7 +450,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works inside assignments', () => {
|
||||
const { replServer } = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
'var log = console.lo',
|
||||
|
|
@ -480,7 +463,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works for defined commands', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
'.b',
|
||||
|
|
@ -503,7 +486,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('does not include __defineSetter__ and friends', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run(['var obj = {};']);
|
||||
|
||||
|
|
@ -522,7 +505,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works with builtin values', () => {
|
||||
const { replServer } = prepareREPL();
|
||||
const { replServer } = startNewREPLServer();
|
||||
|
||||
replServer.complete(
|
||||
'I',
|
||||
|
|
@ -555,7 +538,7 @@ describe('REPL tab completion (core functionality)', () => {
|
|||
});
|
||||
|
||||
it('works with lexically scoped variables', () => {
|
||||
const { replServer, input } = prepareREPL();
|
||||
const { replServer, input } = startNewREPLServer();
|
||||
|
||||
input.run([
|
||||
'let lexicalLet = true;',
|
||||
|
|
|
|||
|
|
@ -5,40 +5,37 @@
|
|||
// should throw.
|
||||
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const repl = require('repl');
|
||||
const assert = require('assert');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
let accum = '';
|
||||
const { replServer, output } = startNewREPLServer(
|
||||
{
|
||||
prompt: '',
|
||||
terminal: false,
|
||||
useColors: false,
|
||||
global: false,
|
||||
},
|
||||
{
|
||||
disableDomainErrorAssert: true
|
||||
},
|
||||
);
|
||||
|
||||
const output = new ArrayStream();
|
||||
output.write = (data) => accum += data.replace('\r', '');
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: new ArrayStream(),
|
||||
output,
|
||||
terminal: false,
|
||||
useColors: false,
|
||||
global: false
|
||||
});
|
||||
|
||||
r.write(
|
||||
replServer.write(
|
||||
'process.nextTick(() => {\n' +
|
||||
' process.on("uncaughtException", () => console.log("Foo"));\n' +
|
||||
' throw new TypeError("foobar");\n' +
|
||||
'});\n'
|
||||
);
|
||||
r.write(
|
||||
replServer.write(
|
||||
'setTimeout(() => {\n' +
|
||||
' throw new RangeError("abc");\n' +
|
||||
'}, 1);console.log()\n'
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
r.close();
|
||||
replServer.close();
|
||||
const len = process.listenerCount('uncaughtException');
|
||||
process.removeAllListeners('uncaughtException');
|
||||
assert.strictEqual(len, 0);
|
||||
assert.match(accum, /ERR_INVALID_REPL_INPUT.*(?!Type)RangeError: abc/s);
|
||||
assert.match(output.accumulator, /ERR_INVALID_REPL_INPUT.*(?!Type)RangeError: abc/s);
|
||||
}, 2);
|
||||
|
|
|
|||
|
|
@ -1,23 +1,27 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { PassThrough } = require('stream');
|
||||
const input = new PassThrough();
|
||||
const output = new PassThrough();
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const r = repl.start({
|
||||
input, output,
|
||||
eval: common.mustCall((code, context, filename, cb) => {
|
||||
r.setPrompt('prompt! ');
|
||||
cb(new Error('err'));
|
||||
})
|
||||
});
|
||||
const { replServer, output } = startNewREPLServer(
|
||||
{
|
||||
prompt: '',
|
||||
terminal: false,
|
||||
useColors: false,
|
||||
global: false,
|
||||
eval: common.mustCall((code, context, filename, cb) => {
|
||||
replServer.setPrompt('prompt! ');
|
||||
cb(new Error('err'));
|
||||
})
|
||||
},
|
||||
{
|
||||
disableDomainErrorAssert: true
|
||||
},
|
||||
);
|
||||
|
||||
input.end('foo\n');
|
||||
replServer.write('foo\n');
|
||||
|
||||
// The output includes exactly one post-error prompt.
|
||||
const out = output.read().toString();
|
||||
assert.match(out, /prompt!/);
|
||||
assert.doesNotMatch(out, /prompt![\S\s]*prompt!/);
|
||||
assert.match(output.accumulator, /prompt!/);
|
||||
assert.doesNotMatch(output.accumulator, /prompt![\S\s]*prompt!/);
|
||||
output.on('data', common.mustNotCall());
|
||||
|
|
|
|||
|
|
@ -1,38 +1,36 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const ArrayStream = require('../common/arraystream');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
let count = 0;
|
||||
|
||||
function run({ command, expected, useColors = false }) {
|
||||
let accum = '';
|
||||
const { replServer, output } = startNewREPLServer(
|
||||
{
|
||||
prompt: '',
|
||||
terminal: false,
|
||||
useColors,
|
||||
},
|
||||
{
|
||||
disableDomainErrorAssert: true
|
||||
},
|
||||
);
|
||||
|
||||
const output = new ArrayStream();
|
||||
output.write = (data) => accum += data.replace('\r', '');
|
||||
replServer.write(`${command}\n`);
|
||||
|
||||
const r = repl.start({
|
||||
prompt: '',
|
||||
input: new ArrayStream(),
|
||||
output,
|
||||
terminal: false,
|
||||
useColors
|
||||
});
|
||||
|
||||
r.write(`${command}\n`);
|
||||
if (typeof expected === 'string') {
|
||||
assert.strictEqual(accum, expected);
|
||||
assert.strictEqual(output.accumulator, expected);
|
||||
} else {
|
||||
assert.match(accum, expected);
|
||||
assert.match(output.accumulator, expected);
|
||||
}
|
||||
|
||||
// Verify that the repl is still working as expected.
|
||||
accum = '';
|
||||
r.write('1 + 1\n');
|
||||
output.accumulator = '';
|
||||
replServer.write('1 + 1\n');
|
||||
// eslint-disable-next-line no-control-regex
|
||||
assert.strictEqual(accum.replace(/\u001b\[[0-9]+m/g, ''), '2\n');
|
||||
r.close();
|
||||
assert.strictEqual(output.accumulator.replace(/\u001b\[[0-9]+m/g, ''), '2\n');
|
||||
replServer.close();
|
||||
count++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,20 +3,25 @@
|
|||
require('../common');
|
||||
const assert = require('assert');
|
||||
const repl = require('repl');
|
||||
const stream = require('stream');
|
||||
const { startNewREPLServer } = require('../common/repl');
|
||||
|
||||
const testingReplPrompt = '_REPL_TESTING_PROMPT_>';
|
||||
|
||||
testSloppyMode();
|
||||
testStrictMode();
|
||||
testMagicMode();
|
||||
testResetContext();
|
||||
testResetContextGlobal();
|
||||
testMagicMode();
|
||||
testError();
|
||||
|
||||
function testSloppyMode() {
|
||||
const r = initRepl(repl.REPL_MODE_SLOPPY);
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
prompt: testingReplPrompt,
|
||||
mode: repl.REPL_MODE_SLOPPY,
|
||||
});
|
||||
|
||||
// Cannot use `let` in sloppy mode
|
||||
r.write(`_; // initial value undefined
|
||||
replServer.write(`_; // initial value undefined
|
||||
var x = 10; // evaluates to undefined
|
||||
_; // still undefined
|
||||
y = 10; // evaluates to 10
|
||||
|
|
@ -29,7 +34,7 @@ function testSloppyMode() {
|
|||
_; // remains 30 from user input
|
||||
`);
|
||||
|
||||
assertOutput(r.output, [
|
||||
assertOutput(output, [
|
||||
'undefined',
|
||||
'undefined',
|
||||
'undefined',
|
||||
|
|
@ -46,9 +51,12 @@ function testSloppyMode() {
|
|||
}
|
||||
|
||||
function testStrictMode() {
|
||||
const r = initRepl(repl.REPL_MODE_STRICT);
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
prompt: testingReplPrompt,
|
||||
mode: repl.REPL_MODE_STRICT,
|
||||
});
|
||||
|
||||
r.write(`_; // initial value undefined
|
||||
replServer.write(`_; // initial value undefined
|
||||
var x = 10; // evaluates to undefined
|
||||
_; // still undefined
|
||||
let _ = 20; // use 'let' only in strict mode - evals to undefined
|
||||
|
|
@ -62,7 +70,7 @@ function testStrictMode() {
|
|||
_; // remains 30 from user input
|
||||
`);
|
||||
|
||||
assertOutput(r.output, [
|
||||
assertOutput(output, [
|
||||
'undefined',
|
||||
'undefined',
|
||||
'undefined',
|
||||
|
|
@ -79,9 +87,12 @@ function testStrictMode() {
|
|||
}
|
||||
|
||||
function testMagicMode() {
|
||||
const r = initRepl(repl.REPL_MODE_MAGIC);
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
prompt: testingReplPrompt,
|
||||
mode: repl.REPL_MODE_MAGIC,
|
||||
});
|
||||
|
||||
r.write(`_; // initial value undefined
|
||||
replServer.write(`_; // initial value undefined
|
||||
x = 10; //
|
||||
_; // last eval - 10
|
||||
let _ = 20; // undefined
|
||||
|
|
@ -95,7 +106,7 @@ function testMagicMode() {
|
|||
_; // remains 30 from user input
|
||||
`);
|
||||
|
||||
assertOutput(r.output, [
|
||||
assertOutput(output, [
|
||||
'undefined',
|
||||
'10',
|
||||
'10',
|
||||
|
|
@ -112,9 +123,12 @@ function testMagicMode() {
|
|||
}
|
||||
|
||||
function testResetContext() {
|
||||
const r = initRepl(repl.REPL_MODE_SLOPPY);
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
prompt: testingReplPrompt,
|
||||
mode: repl.REPL_MODE_MAGIC,
|
||||
});
|
||||
|
||||
r.write(`_ = 10; // explicitly set to 10
|
||||
replServer.write(`_ = 10; // explicitly set to 10
|
||||
_; // 10 from user input
|
||||
.clear // Clearing context...
|
||||
_; // remains 10
|
||||
|
|
@ -122,7 +136,7 @@ function testResetContext() {
|
|||
_; // expect 20
|
||||
`);
|
||||
|
||||
assertOutput(r.output, [
|
||||
assertOutput(output, [
|
||||
'Expression assignment to _ now disabled.',
|
||||
'10',
|
||||
'10',
|
||||
|
|
@ -134,15 +148,18 @@ function testResetContext() {
|
|||
}
|
||||
|
||||
function testResetContextGlobal() {
|
||||
const r = initRepl(repl.REPL_MODE_STRICT, true);
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
prompt: testingReplPrompt,
|
||||
useGlobal: true,
|
||||
});
|
||||
|
||||
r.write(`_ = 10; // explicitly set to 10
|
||||
replServer.write(`_ = 10; // explicitly set to 10
|
||||
_; // 10 from user input
|
||||
.clear // No output because useGlobal is true
|
||||
_; // remains 10
|
||||
`);
|
||||
|
||||
assertOutput(r.output, [
|
||||
assertOutput(output, [
|
||||
'Expression assignment to _ now disabled.',
|
||||
'10',
|
||||
'10',
|
||||
|
|
@ -155,9 +172,15 @@ function testResetContextGlobal() {
|
|||
}
|
||||
|
||||
function testError() {
|
||||
const r = initRepl(repl.REPL_MODE_STRICT);
|
||||
const { replServer, output } = startNewREPLServer({
|
||||
prompt: testingReplPrompt,
|
||||
replMode: repl.REPL_MODE_STRICT,
|
||||
preview: false,
|
||||
}, {
|
||||
disableDomainErrorAssert: true
|
||||
});
|
||||
|
||||
r.write(`_error; // initial value undefined
|
||||
replServer.write(`_error; // initial value undefined
|
||||
throw new Error('foo'); // throws error
|
||||
_error; // shows error
|
||||
fs.readdirSync('/nonexistent?'); // throws error, sync
|
||||
|
|
@ -168,7 +191,9 @@ function testError() {
|
|||
`);
|
||||
|
||||
setImmediate(() => {
|
||||
const lines = r.output.accum.trim().split('\n');
|
||||
const lines = output.accumulator.trim().split('\n').filter(
|
||||
(line) => !line.includes(testingReplPrompt) || line.includes('Uncaught Error')
|
||||
);
|
||||
const expectedLines = [
|
||||
'undefined',
|
||||
|
||||
|
|
@ -192,7 +217,7 @@ function testError() {
|
|||
'undefined',
|
||||
|
||||
// The message from the original throw
|
||||
'Uncaught Error: baz',
|
||||
/Uncaught Error: baz/,
|
||||
];
|
||||
for (const line of lines) {
|
||||
const expected = expectedLines.shift();
|
||||
|
|
@ -204,14 +229,14 @@ function testError() {
|
|||
assert.strictEqual(expectedLines.length, 0);
|
||||
|
||||
// Reset output, check that '_error' is the asynchronously caught error.
|
||||
r.output.accum = '';
|
||||
r.write(`_error.message // show the message
|
||||
output.accumulator = '';
|
||||
replServer.write(`_error.message // show the message
|
||||
_error = 0; // disable auto-assignment
|
||||
throw new Error('quux'); // new error
|
||||
_error; // should not see the new error
|
||||
`);
|
||||
|
||||
assertOutput(r.output, [
|
||||
assertOutput(output, [
|
||||
"'baz'",
|
||||
'Expression assignment to _error now disabled.',
|
||||
'0',
|
||||
|
|
@ -221,27 +246,7 @@ function testError() {
|
|||
});
|
||||
}
|
||||
|
||||
function initRepl(mode, useGlobal) {
|
||||
const inputStream = new stream.PassThrough();
|
||||
const outputStream = new stream.PassThrough();
|
||||
outputStream.accum = '';
|
||||
|
||||
outputStream.on('data', (data) => {
|
||||
outputStream.accum += data;
|
||||
});
|
||||
|
||||
return repl.start({
|
||||
input: inputStream,
|
||||
output: outputStream,
|
||||
useColors: false,
|
||||
terminal: false,
|
||||
prompt: '',
|
||||
replMode: mode,
|
||||
useGlobal: useGlobal
|
||||
});
|
||||
}
|
||||
|
||||
function assertOutput(output, expected) {
|
||||
const lines = output.accum.trim().split('\n');
|
||||
const lines = output.accumulator.trim().split('\n').filter((line) => !line.includes(testingReplPrompt));
|
||||
assert.deepStrictEqual(lines, expected);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user