11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciconst spawn = require('child_process').spawn; 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst BREAK_MESSAGE = new RegExp('(?:' + [ 61cb0ef41Sopenharmony_ci 'assert', 'break', 'break on start', 'debugCommand', 71cb0ef41Sopenharmony_ci 'exception', 'other', 'promiseRejection', 81cb0ef41Sopenharmony_ci].join('|') + ') in', 'i'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cilet TIMEOUT = common.platformTimeout(5000); 111cb0ef41Sopenharmony_ciif (common.isWindows) { 121cb0ef41Sopenharmony_ci // Some of the windows machines in the CI need more time to receive 131cb0ef41Sopenharmony_ci // the outputs from the client. 141cb0ef41Sopenharmony_ci // https://github.com/nodejs/build/issues/3014 151cb0ef41Sopenharmony_ci TIMEOUT = common.platformTimeout(15000); 161cb0ef41Sopenharmony_ci} 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cifunction isPreBreak(output) { 191cb0ef41Sopenharmony_ci return /Break on start/.test(output) && /1 \(function \(exports/.test(output); 201cb0ef41Sopenharmony_ci} 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cifunction startCLI(args, flags = [], spawnOpts = {}) { 231cb0ef41Sopenharmony_ci let stderrOutput = ''; 241cb0ef41Sopenharmony_ci const child = 251cb0ef41Sopenharmony_ci spawn(process.execPath, [...flags, 'inspect', ...args], spawnOpts); 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci const outputBuffer = []; 281cb0ef41Sopenharmony_ci function bufferOutput(chunk) { 291cb0ef41Sopenharmony_ci if (this === child.stderr) { 301cb0ef41Sopenharmony_ci stderrOutput += chunk; 311cb0ef41Sopenharmony_ci } 321cb0ef41Sopenharmony_ci outputBuffer.push(chunk); 331cb0ef41Sopenharmony_ci } 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci function getOutput() { 361cb0ef41Sopenharmony_ci return outputBuffer.join('\n').replaceAll('\b', ''); 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci child.stdout.setEncoding('utf8'); 401cb0ef41Sopenharmony_ci child.stdout.on('data', bufferOutput); 411cb0ef41Sopenharmony_ci child.stderr.setEncoding('utf8'); 421cb0ef41Sopenharmony_ci child.stderr.on('data', bufferOutput); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci if (process.env.VERBOSE === '1') { 451cb0ef41Sopenharmony_ci child.stdout.pipe(process.stdout); 461cb0ef41Sopenharmony_ci child.stderr.pipe(process.stderr); 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci return { 501cb0ef41Sopenharmony_ci flushOutput() { 511cb0ef41Sopenharmony_ci const output = this.output; 521cb0ef41Sopenharmony_ci outputBuffer.length = 0; 531cb0ef41Sopenharmony_ci return output; 541cb0ef41Sopenharmony_ci }, 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci waitFor(pattern) { 571cb0ef41Sopenharmony_ci function checkPattern(str) { 581cb0ef41Sopenharmony_ci if (Array.isArray(pattern)) { 591cb0ef41Sopenharmony_ci return pattern.every((p) => p.test(str)); 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci return pattern.test(str); 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci return new Promise((resolve, reject) => { 651cb0ef41Sopenharmony_ci function checkOutput() { 661cb0ef41Sopenharmony_ci if (checkPattern(getOutput())) { 671cb0ef41Sopenharmony_ci tearDown(); 681cb0ef41Sopenharmony_ci resolve(); 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci function onChildClose(code, signal) { 731cb0ef41Sopenharmony_ci tearDown(); 741cb0ef41Sopenharmony_ci let message = 'Child exited'; 751cb0ef41Sopenharmony_ci if (code) { 761cb0ef41Sopenharmony_ci message += `, code ${code}`; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci if (signal) { 791cb0ef41Sopenharmony_ci message += `, signal ${signal}`; 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci message += ` while waiting for ${pattern}; found: ${this.output}`; 821cb0ef41Sopenharmony_ci if (stderrOutput) { 831cb0ef41Sopenharmony_ci message += `\n STDERR: ${stderrOutput}`; 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci reject(new Error(message)); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci const timer = setTimeout(() => { 891cb0ef41Sopenharmony_ci tearDown(); 901cb0ef41Sopenharmony_ci reject(new Error([ 911cb0ef41Sopenharmony_ci `Timeout (${TIMEOUT}) while waiting for ${pattern}`, 921cb0ef41Sopenharmony_ci `found: ${this.output}`, 931cb0ef41Sopenharmony_ci ].join('; '))); 941cb0ef41Sopenharmony_ci }, TIMEOUT); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci function tearDown() { 971cb0ef41Sopenharmony_ci clearTimeout(timer); 981cb0ef41Sopenharmony_ci child.stdout.removeListener('data', checkOutput); 991cb0ef41Sopenharmony_ci child.removeListener('close', onChildClose); 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci child.on('close', onChildClose); 1031cb0ef41Sopenharmony_ci child.stdout.on('data', checkOutput); 1041cb0ef41Sopenharmony_ci checkOutput(); 1051cb0ef41Sopenharmony_ci }); 1061cb0ef41Sopenharmony_ci }, 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci waitForPrompt() { 1091cb0ef41Sopenharmony_ci return this.waitFor(/>\s+$/); 1101cb0ef41Sopenharmony_ci }, 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci async waitForInitialBreak() { 1131cb0ef41Sopenharmony_ci await this.waitFor(/break (?:on start )?in/i); 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci if (isPreBreak(this.output)) { 1161cb0ef41Sopenharmony_ci await this.command('next', false); 1171cb0ef41Sopenharmony_ci return this.waitFor(/break in/); 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci }, 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci get breakInfo() { 1221cb0ef41Sopenharmony_ci const output = this.output; 1231cb0ef41Sopenharmony_ci const breakMatch = 1241cb0ef41Sopenharmony_ci output.match(/break (?:on start )?in ([^\n]+):(\d+)\n/i); 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci if (breakMatch === null) { 1271cb0ef41Sopenharmony_ci throw new Error( 1281cb0ef41Sopenharmony_ci `Could not find breakpoint info in ${JSON.stringify(output)}`); 1291cb0ef41Sopenharmony_ci } 1301cb0ef41Sopenharmony_ci return { filename: breakMatch[1], line: +breakMatch[2] }; 1311cb0ef41Sopenharmony_ci }, 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci ctrlC() { 1341cb0ef41Sopenharmony_ci return this.command('.interrupt'); 1351cb0ef41Sopenharmony_ci }, 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci get output() { 1381cb0ef41Sopenharmony_ci return getOutput(); 1391cb0ef41Sopenharmony_ci }, 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci get rawOutput() { 1421cb0ef41Sopenharmony_ci return outputBuffer.join('').toString(); 1431cb0ef41Sopenharmony_ci }, 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci parseSourceLines() { 1461cb0ef41Sopenharmony_ci return getOutput().split('\n') 1471cb0ef41Sopenharmony_ci .map((line) => line.match(/(?:\*|>)?\s*(\d+)/)) 1481cb0ef41Sopenharmony_ci .filter((match) => match !== null) 1491cb0ef41Sopenharmony_ci .map((match) => +match[1]); 1501cb0ef41Sopenharmony_ci }, 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci writeLine(input, flush = true) { 1531cb0ef41Sopenharmony_ci if (flush) { 1541cb0ef41Sopenharmony_ci this.flushOutput(); 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci if (process.env.VERBOSE === '1') { 1571cb0ef41Sopenharmony_ci process.stderr.write(`< ${input}\n`); 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci child.stdin.write(input); 1601cb0ef41Sopenharmony_ci child.stdin.write('\n'); 1611cb0ef41Sopenharmony_ci }, 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci command(input, flush = true) { 1641cb0ef41Sopenharmony_ci this.writeLine(input, flush); 1651cb0ef41Sopenharmony_ci return this.waitForPrompt(); 1661cb0ef41Sopenharmony_ci }, 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci stepCommand(input) { 1691cb0ef41Sopenharmony_ci this.writeLine(input, true); 1701cb0ef41Sopenharmony_ci return this 1711cb0ef41Sopenharmony_ci .waitFor(BREAK_MESSAGE) 1721cb0ef41Sopenharmony_ci .then(() => this.waitForPrompt()); 1731cb0ef41Sopenharmony_ci }, 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci quit() { 1761cb0ef41Sopenharmony_ci return new Promise((resolve) => { 1771cb0ef41Sopenharmony_ci child.stdin.end(); 1781cb0ef41Sopenharmony_ci child.on('close', resolve); 1791cb0ef41Sopenharmony_ci }); 1801cb0ef41Sopenharmony_ci }, 1811cb0ef41Sopenharmony_ci }; 1821cb0ef41Sopenharmony_ci} 1831cb0ef41Sopenharmony_cimodule.exports = startCLI; 184