11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_cirequire('../common'); 41cb0ef41Sopenharmony_ciconst assert = require('assert'); 51cb0ef41Sopenharmony_ciconst repl = require('repl'); 61cb0ef41Sopenharmony_ciconst stream = require('stream'); 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_citestSloppyMode(); 91cb0ef41Sopenharmony_citestStrictMode(); 101cb0ef41Sopenharmony_citestResetContext(); 111cb0ef41Sopenharmony_citestResetContextGlobal(); 121cb0ef41Sopenharmony_citestMagicMode(); 131cb0ef41Sopenharmony_citestError(); 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cifunction testSloppyMode() { 161cb0ef41Sopenharmony_ci const r = initRepl(repl.REPL_MODE_SLOPPY); 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci // Cannot use `let` in sloppy mode 191cb0ef41Sopenharmony_ci r.write(`_; // initial value undefined 201cb0ef41Sopenharmony_ci var x = 10; // evaluates to undefined 211cb0ef41Sopenharmony_ci _; // still undefined 221cb0ef41Sopenharmony_ci y = 10; // evaluates to 10 231cb0ef41Sopenharmony_ci _; // 10 from last eval 241cb0ef41Sopenharmony_ci _ = 20; // explicitly set to 20 251cb0ef41Sopenharmony_ci _; // 20 from user input 261cb0ef41Sopenharmony_ci _ = 30; // make sure we can set it twice and no prompt 271cb0ef41Sopenharmony_ci _; // 30 from user input 281cb0ef41Sopenharmony_ci y = 40; // make sure eval doesn't change _ 291cb0ef41Sopenharmony_ci _; // remains 30 from user input 301cb0ef41Sopenharmony_ci `); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci assertOutput(r.output, [ 331cb0ef41Sopenharmony_ci 'undefined', 341cb0ef41Sopenharmony_ci 'undefined', 351cb0ef41Sopenharmony_ci 'undefined', 361cb0ef41Sopenharmony_ci '10', 371cb0ef41Sopenharmony_ci '10', 381cb0ef41Sopenharmony_ci 'Expression assignment to _ now disabled.', 391cb0ef41Sopenharmony_ci '20', 401cb0ef41Sopenharmony_ci '20', 411cb0ef41Sopenharmony_ci '30', 421cb0ef41Sopenharmony_ci '30', 431cb0ef41Sopenharmony_ci '40', 441cb0ef41Sopenharmony_ci '30', 451cb0ef41Sopenharmony_ci ]); 461cb0ef41Sopenharmony_ci} 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_cifunction testStrictMode() { 491cb0ef41Sopenharmony_ci const r = initRepl(repl.REPL_MODE_STRICT); 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci r.write(`_; // initial value undefined 521cb0ef41Sopenharmony_ci var x = 10; // evaluates to undefined 531cb0ef41Sopenharmony_ci _; // still undefined 541cb0ef41Sopenharmony_ci let _ = 20; // use 'let' only in strict mode - evals to undefined 551cb0ef41Sopenharmony_ci _; // 20 from user input 561cb0ef41Sopenharmony_ci _ = 30; // make sure we can set it twice and no prompt 571cb0ef41Sopenharmony_ci _; // 30 from user input 581cb0ef41Sopenharmony_ci var y = 40; // make sure eval doesn't change _ 591cb0ef41Sopenharmony_ci _; // remains 30 from user input 601cb0ef41Sopenharmony_ci function f() { let _ = 50; } // undefined 611cb0ef41Sopenharmony_ci f(); // undefined 621cb0ef41Sopenharmony_ci _; // remains 30 from user input 631cb0ef41Sopenharmony_ci `); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci assertOutput(r.output, [ 661cb0ef41Sopenharmony_ci 'undefined', 671cb0ef41Sopenharmony_ci 'undefined', 681cb0ef41Sopenharmony_ci 'undefined', 691cb0ef41Sopenharmony_ci 'undefined', 701cb0ef41Sopenharmony_ci '20', 711cb0ef41Sopenharmony_ci '30', 721cb0ef41Sopenharmony_ci '30', 731cb0ef41Sopenharmony_ci 'undefined', 741cb0ef41Sopenharmony_ci '30', 751cb0ef41Sopenharmony_ci 'undefined', 761cb0ef41Sopenharmony_ci 'undefined', 771cb0ef41Sopenharmony_ci '30', 781cb0ef41Sopenharmony_ci ]); 791cb0ef41Sopenharmony_ci} 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_cifunction testMagicMode() { 821cb0ef41Sopenharmony_ci const r = initRepl(repl.REPL_MODE_MAGIC); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci r.write(`_; // initial value undefined 851cb0ef41Sopenharmony_ci x = 10; // 861cb0ef41Sopenharmony_ci _; // last eval - 10 871cb0ef41Sopenharmony_ci let _ = 20; // undefined 881cb0ef41Sopenharmony_ci _; // 20 from user input 891cb0ef41Sopenharmony_ci _ = 30; // make sure we can set it twice and no prompt 901cb0ef41Sopenharmony_ci _; // 30 from user input 911cb0ef41Sopenharmony_ci var y = 40; // make sure eval doesn't change _ 921cb0ef41Sopenharmony_ci _; // remains 30 from user input 931cb0ef41Sopenharmony_ci function f() { let _ = 50; return _; } // undefined 941cb0ef41Sopenharmony_ci f(); // 50 951cb0ef41Sopenharmony_ci _; // remains 30 from user input 961cb0ef41Sopenharmony_ci `); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci assertOutput(r.output, [ 991cb0ef41Sopenharmony_ci 'undefined', 1001cb0ef41Sopenharmony_ci '10', 1011cb0ef41Sopenharmony_ci '10', 1021cb0ef41Sopenharmony_ci 'undefined', 1031cb0ef41Sopenharmony_ci '20', 1041cb0ef41Sopenharmony_ci '30', 1051cb0ef41Sopenharmony_ci '30', 1061cb0ef41Sopenharmony_ci 'undefined', 1071cb0ef41Sopenharmony_ci '30', 1081cb0ef41Sopenharmony_ci 'undefined', 1091cb0ef41Sopenharmony_ci '50', 1101cb0ef41Sopenharmony_ci '30', 1111cb0ef41Sopenharmony_ci ]); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_cifunction testResetContext() { 1151cb0ef41Sopenharmony_ci const r = initRepl(repl.REPL_MODE_SLOPPY); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci r.write(`_ = 10; // explicitly set to 10 1181cb0ef41Sopenharmony_ci _; // 10 from user input 1191cb0ef41Sopenharmony_ci .clear // Clearing context... 1201cb0ef41Sopenharmony_ci _; // remains 10 1211cb0ef41Sopenharmony_ci x = 20; // but behavior reverts to last eval 1221cb0ef41Sopenharmony_ci _; // expect 20 1231cb0ef41Sopenharmony_ci `); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci assertOutput(r.output, [ 1261cb0ef41Sopenharmony_ci 'Expression assignment to _ now disabled.', 1271cb0ef41Sopenharmony_ci '10', 1281cb0ef41Sopenharmony_ci '10', 1291cb0ef41Sopenharmony_ci 'Clearing context...', 1301cb0ef41Sopenharmony_ci '10', 1311cb0ef41Sopenharmony_ci '20', 1321cb0ef41Sopenharmony_ci '20', 1331cb0ef41Sopenharmony_ci ]); 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_cifunction testResetContextGlobal() { 1371cb0ef41Sopenharmony_ci const r = initRepl(repl.REPL_MODE_STRICT, true); 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci r.write(`_ = 10; // explicitly set to 10 1401cb0ef41Sopenharmony_ci _; // 10 from user input 1411cb0ef41Sopenharmony_ci .clear // No output because useGlobal is true 1421cb0ef41Sopenharmony_ci _; // remains 10 1431cb0ef41Sopenharmony_ci `); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci assertOutput(r.output, [ 1461cb0ef41Sopenharmony_ci 'Expression assignment to _ now disabled.', 1471cb0ef41Sopenharmony_ci '10', 1481cb0ef41Sopenharmony_ci '10', 1491cb0ef41Sopenharmony_ci '10', 1501cb0ef41Sopenharmony_ci ]); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci // Delete globals leaked by REPL when `useGlobal` is `true` 1531cb0ef41Sopenharmony_ci delete global.module; 1541cb0ef41Sopenharmony_ci delete global.require; 1551cb0ef41Sopenharmony_ci} 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_cifunction testError() { 1581cb0ef41Sopenharmony_ci const r = initRepl(repl.REPL_MODE_STRICT); 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci r.write(`_error; // initial value undefined 1611cb0ef41Sopenharmony_ci throw new Error('foo'); // throws error 1621cb0ef41Sopenharmony_ci _error; // shows error 1631cb0ef41Sopenharmony_ci fs.readdirSync('/nonexistent?'); // throws error, sync 1641cb0ef41Sopenharmony_ci _error.code; // shows error code 1651cb0ef41Sopenharmony_ci _error.syscall; // shows error syscall 1661cb0ef41Sopenharmony_ci setImmediate(() => { throw new Error('baz'); }); undefined; 1671cb0ef41Sopenharmony_ci // throws error, async 1681cb0ef41Sopenharmony_ci `); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci setImmediate(() => { 1711cb0ef41Sopenharmony_ci const lines = r.output.accum.trim().split('\n'); 1721cb0ef41Sopenharmony_ci const expectedLines = [ 1731cb0ef41Sopenharmony_ci 'undefined', 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci // The error, both from the original throw and the `_error` echo. 1761cb0ef41Sopenharmony_ci 'Uncaught Error: foo', 1771cb0ef41Sopenharmony_ci '[Error: foo]', 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci // The sync error, with individual property echoes 1801cb0ef41Sopenharmony_ci /^Uncaught Error: ENOENT: no such file or directory, scandir '.*nonexistent\?'/, 1811cb0ef41Sopenharmony_ci /Object\.readdirSync/, 1821cb0ef41Sopenharmony_ci /^ {2}errno: -(2|4058),$/, 1831cb0ef41Sopenharmony_ci " syscall: 'scandir',", 1841cb0ef41Sopenharmony_ci " code: 'ENOENT',", 1851cb0ef41Sopenharmony_ci " path: '/nonexistent?'", 1861cb0ef41Sopenharmony_ci '}', 1871cb0ef41Sopenharmony_ci "'ENOENT'", 1881cb0ef41Sopenharmony_ci "'scandir'", 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci // Dummy 'undefined' from the explicit silencer + one from the comment 1911cb0ef41Sopenharmony_ci 'undefined', 1921cb0ef41Sopenharmony_ci 'undefined', 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci // The message from the original throw 1951cb0ef41Sopenharmony_ci 'Uncaught Error: baz', 1961cb0ef41Sopenharmony_ci ]; 1971cb0ef41Sopenharmony_ci for (const line of lines) { 1981cb0ef41Sopenharmony_ci const expected = expectedLines.shift(); 1991cb0ef41Sopenharmony_ci if (typeof expected === 'string') 2001cb0ef41Sopenharmony_ci assert.strictEqual(line, expected); 2011cb0ef41Sopenharmony_ci else 2021cb0ef41Sopenharmony_ci assert.match(line, expected); 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci assert.strictEqual(expectedLines.length, 0); 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci // Reset output, check that '_error' is the asynchronously caught error. 2071cb0ef41Sopenharmony_ci r.output.accum = ''; 2081cb0ef41Sopenharmony_ci r.write(`_error.message // show the message 2091cb0ef41Sopenharmony_ci _error = 0; // disable auto-assignment 2101cb0ef41Sopenharmony_ci throw new Error('quux'); // new error 2111cb0ef41Sopenharmony_ci _error; // should not see the new error 2121cb0ef41Sopenharmony_ci `); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci assertOutput(r.output, [ 2151cb0ef41Sopenharmony_ci "'baz'", 2161cb0ef41Sopenharmony_ci 'Expression assignment to _error now disabled.', 2171cb0ef41Sopenharmony_ci '0', 2181cb0ef41Sopenharmony_ci 'Uncaught Error: quux', 2191cb0ef41Sopenharmony_ci '0', 2201cb0ef41Sopenharmony_ci ]); 2211cb0ef41Sopenharmony_ci }); 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_cifunction initRepl(mode, useGlobal) { 2251cb0ef41Sopenharmony_ci const inputStream = new stream.PassThrough(); 2261cb0ef41Sopenharmony_ci const outputStream = new stream.PassThrough(); 2271cb0ef41Sopenharmony_ci outputStream.accum = ''; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci outputStream.on('data', (data) => { 2301cb0ef41Sopenharmony_ci outputStream.accum += data; 2311cb0ef41Sopenharmony_ci }); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci return repl.start({ 2341cb0ef41Sopenharmony_ci input: inputStream, 2351cb0ef41Sopenharmony_ci output: outputStream, 2361cb0ef41Sopenharmony_ci useColors: false, 2371cb0ef41Sopenharmony_ci terminal: false, 2381cb0ef41Sopenharmony_ci prompt: '', 2391cb0ef41Sopenharmony_ci replMode: mode, 2401cb0ef41Sopenharmony_ci useGlobal: useGlobal 2411cb0ef41Sopenharmony_ci }); 2421cb0ef41Sopenharmony_ci} 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_cifunction assertOutput(output, expected) { 2451cb0ef41Sopenharmony_ci const lines = output.accum.trim().split('\n'); 2461cb0ef41Sopenharmony_ci assert.deepStrictEqual(lines, expected); 2471cb0ef41Sopenharmony_ci} 248