11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { 41cb0ef41Sopenharmony_ci ArrayPrototypeForEach, 51cb0ef41Sopenharmony_ci ArrayPrototypeJoin, 61cb0ef41Sopenharmony_ci ArrayPrototypeMap, 71cb0ef41Sopenharmony_ci ArrayPrototypePop, 81cb0ef41Sopenharmony_ci ArrayPrototypePushApply, 91cb0ef41Sopenharmony_ci ArrayPrototypeShift, 101cb0ef41Sopenharmony_ci ArrayPrototypeSlice, 111cb0ef41Sopenharmony_ci FunctionPrototypeBind, 121cb0ef41Sopenharmony_ci Number, 131cb0ef41Sopenharmony_ci Promise, 141cb0ef41Sopenharmony_ci PromisePrototypeThen, 151cb0ef41Sopenharmony_ci PromiseResolve, 161cb0ef41Sopenharmony_ci Proxy, 171cb0ef41Sopenharmony_ci RegExpPrototypeExec, 181cb0ef41Sopenharmony_ci RegExpPrototypeSymbolSplit, 191cb0ef41Sopenharmony_ci StringPrototypeEndsWith, 201cb0ef41Sopenharmony_ci StringPrototypeSplit, 211cb0ef41Sopenharmony_ci} = primordials; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ciconst { spawn } = require('child_process'); 241cb0ef41Sopenharmony_ciconst { EventEmitter } = require('events'); 251cb0ef41Sopenharmony_ciconst net = require('net'); 261cb0ef41Sopenharmony_ciconst util = require('util'); 271cb0ef41Sopenharmony_ciconst { 281cb0ef41Sopenharmony_ci setInterval: pSetInterval, 291cb0ef41Sopenharmony_ci setTimeout: pSetTimeout, 301cb0ef41Sopenharmony_ci} = require('timers/promises'); 311cb0ef41Sopenharmony_ciconst { 321cb0ef41Sopenharmony_ci AbortController, 331cb0ef41Sopenharmony_ci} = require('internal/abort_controller'); 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ciconst { 0: InspectClient, 1: createRepl } = 361cb0ef41Sopenharmony_ci [ 371cb0ef41Sopenharmony_ci require('internal/debugger/inspect_client'), 381cb0ef41Sopenharmony_ci require('internal/debugger/inspect_repl'), 391cb0ef41Sopenharmony_ci ]; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciconst debuglog = util.debuglog('inspect'); 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ciconst { ERR_DEBUGGER_STARTUP_ERROR } = require('internal/errors').codes; 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciasync function portIsFree(host, port, timeout = 3000) { 461cb0ef41Sopenharmony_ci if (port === 0) return; // Binding to a random port. 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci const retryDelay = 150; 491cb0ef41Sopenharmony_ci const ac = new AbortController(); 501cb0ef41Sopenharmony_ci const { signal } = ac; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci pSetTimeout(timeout).then(() => ac.abort()); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci const asyncIterator = pSetInterval(retryDelay); 551cb0ef41Sopenharmony_ci while (true) { 561cb0ef41Sopenharmony_ci await asyncIterator.next(); 571cb0ef41Sopenharmony_ci if (signal.aborted) { 581cb0ef41Sopenharmony_ci throw new ERR_DEBUGGER_STARTUP_ERROR( 591cb0ef41Sopenharmony_ci `Timeout (${timeout}) waiting for ${host}:${port} to be free`); 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci const error = await new Promise((resolve) => { 621cb0ef41Sopenharmony_ci const socket = net.connect(port, host); 631cb0ef41Sopenharmony_ci socket.on('error', resolve); 641cb0ef41Sopenharmony_ci socket.on('connect', () => { 651cb0ef41Sopenharmony_ci socket.end(); 661cb0ef41Sopenharmony_ci resolve(); 671cb0ef41Sopenharmony_ci }); 681cb0ef41Sopenharmony_ci }); 691cb0ef41Sopenharmony_ci if (error?.code === 'ECONNREFUSED') { 701cb0ef41Sopenharmony_ci return; 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci} 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ciconst debugRegex = /Debugger listening on ws:\/\/\[?(.+?)\]?:(\d+)\//; 761cb0ef41Sopenharmony_ciasync function runScript(script, scriptArgs, inspectHost, inspectPort, 771cb0ef41Sopenharmony_ci childPrint) { 781cb0ef41Sopenharmony_ci await portIsFree(inspectHost, inspectPort); 791cb0ef41Sopenharmony_ci const args = [`--inspect-brk=${inspectPort}`, script]; 801cb0ef41Sopenharmony_ci ArrayPrototypePushApply(args, scriptArgs); 811cb0ef41Sopenharmony_ci const child = spawn(process.execPath, args); 821cb0ef41Sopenharmony_ci child.stdout.setEncoding('utf8'); 831cb0ef41Sopenharmony_ci child.stderr.setEncoding('utf8'); 841cb0ef41Sopenharmony_ci child.stdout.on('data', (chunk) => childPrint(chunk, 'stdout')); 851cb0ef41Sopenharmony_ci child.stderr.on('data', (chunk) => childPrint(chunk, 'stderr')); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci let output = ''; 881cb0ef41Sopenharmony_ci return new Promise((resolve) => { 891cb0ef41Sopenharmony_ci function waitForListenHint(text) { 901cb0ef41Sopenharmony_ci output += text; 911cb0ef41Sopenharmony_ci const debug = RegExpPrototypeExec(debugRegex, output); 921cb0ef41Sopenharmony_ci if (debug) { 931cb0ef41Sopenharmony_ci const host = debug[1]; 941cb0ef41Sopenharmony_ci const port = Number(debug[2]); 951cb0ef41Sopenharmony_ci child.stderr.removeListener('data', waitForListenHint); 961cb0ef41Sopenharmony_ci resolve([child, port, host]); 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci child.stderr.on('data', waitForListenHint); 1011cb0ef41Sopenharmony_ci }); 1021cb0ef41Sopenharmony_ci} 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_cifunction createAgentProxy(domain, client) { 1051cb0ef41Sopenharmony_ci const agent = new EventEmitter(); 1061cb0ef41Sopenharmony_ci agent.then = (then, _catch) => { 1071cb0ef41Sopenharmony_ci // TODO: potentially fetch the protocol and pretty-print it here. 1081cb0ef41Sopenharmony_ci const descriptor = { 1091cb0ef41Sopenharmony_ci [util.inspect.custom](depth, { stylize }) { 1101cb0ef41Sopenharmony_ci return stylize(`[Agent ${domain}]`, 'special'); 1111cb0ef41Sopenharmony_ci }, 1121cb0ef41Sopenharmony_ci }; 1131cb0ef41Sopenharmony_ci return PromisePrototypeThen(PromiseResolve(descriptor), then, _catch); 1141cb0ef41Sopenharmony_ci }; 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci return new Proxy(agent, { 1171cb0ef41Sopenharmony_ci __proto__: null, 1181cb0ef41Sopenharmony_ci get(target, name) { 1191cb0ef41Sopenharmony_ci if (name in target) return target[name]; 1201cb0ef41Sopenharmony_ci return function callVirtualMethod(params) { 1211cb0ef41Sopenharmony_ci return client.callMethod(`${domain}.${name}`, params); 1221cb0ef41Sopenharmony_ci }; 1231cb0ef41Sopenharmony_ci }, 1241cb0ef41Sopenharmony_ci }); 1251cb0ef41Sopenharmony_ci} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ciclass NodeInspector { 1281cb0ef41Sopenharmony_ci constructor(options, stdin, stdout) { 1291cb0ef41Sopenharmony_ci this.options = options; 1301cb0ef41Sopenharmony_ci this.stdin = stdin; 1311cb0ef41Sopenharmony_ci this.stdout = stdout; 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci this.paused = true; 1341cb0ef41Sopenharmony_ci this.child = null; 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci if (options.script) { 1371cb0ef41Sopenharmony_ci this._runScript = FunctionPrototypeBind( 1381cb0ef41Sopenharmony_ci runScript, null, 1391cb0ef41Sopenharmony_ci options.script, 1401cb0ef41Sopenharmony_ci options.scriptArgs, 1411cb0ef41Sopenharmony_ci options.host, 1421cb0ef41Sopenharmony_ci options.port, 1431cb0ef41Sopenharmony_ci FunctionPrototypeBind(this.childPrint, this)); 1441cb0ef41Sopenharmony_ci } else { 1451cb0ef41Sopenharmony_ci this._runScript = 1461cb0ef41Sopenharmony_ci () => PromiseResolve([null, options.port, options.host]); 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci this.client = new InspectClient(); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci this.domainNames = ['Debugger', 'HeapProfiler', 'Profiler', 'Runtime']; 1521cb0ef41Sopenharmony_ci ArrayPrototypeForEach(this.domainNames, (domain) => { 1531cb0ef41Sopenharmony_ci this[domain] = createAgentProxy(domain, this.client); 1541cb0ef41Sopenharmony_ci }); 1551cb0ef41Sopenharmony_ci this.handleDebugEvent = (fullName, params) => { 1561cb0ef41Sopenharmony_ci const { 0: domain, 1: name } = StringPrototypeSplit(fullName, '.'); 1571cb0ef41Sopenharmony_ci if (domain in this) { 1581cb0ef41Sopenharmony_ci this[domain].emit(name, params); 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci }; 1611cb0ef41Sopenharmony_ci this.client.on('debugEvent', this.handleDebugEvent); 1621cb0ef41Sopenharmony_ci const startRepl = createRepl(this); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci // Handle all possible exits 1651cb0ef41Sopenharmony_ci process.on('exit', () => this.killChild()); 1661cb0ef41Sopenharmony_ci const exitCodeZero = () => process.exit(0); 1671cb0ef41Sopenharmony_ci process.once('SIGTERM', exitCodeZero); 1681cb0ef41Sopenharmony_ci process.once('SIGHUP', exitCodeZero); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci (async () => { 1711cb0ef41Sopenharmony_ci try { 1721cb0ef41Sopenharmony_ci await this.run(); 1731cb0ef41Sopenharmony_ci const repl = await startRepl(); 1741cb0ef41Sopenharmony_ci this.repl = repl; 1751cb0ef41Sopenharmony_ci this.repl.on('exit', exitCodeZero); 1761cb0ef41Sopenharmony_ci this.paused = false; 1771cb0ef41Sopenharmony_ci } catch (error) { 1781cb0ef41Sopenharmony_ci process.nextTick(() => { throw error; }); 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci })(); 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci suspendReplWhile(fn) { 1841cb0ef41Sopenharmony_ci if (this.repl) { 1851cb0ef41Sopenharmony_ci this.repl.pause(); 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci this.stdin.pause(); 1881cb0ef41Sopenharmony_ci this.paused = true; 1891cb0ef41Sopenharmony_ci return (async () => { 1901cb0ef41Sopenharmony_ci try { 1911cb0ef41Sopenharmony_ci await fn(); 1921cb0ef41Sopenharmony_ci this.paused = false; 1931cb0ef41Sopenharmony_ci if (this.repl) { 1941cb0ef41Sopenharmony_ci this.repl.resume(); 1951cb0ef41Sopenharmony_ci this.repl.displayPrompt(); 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci this.stdin.resume(); 1981cb0ef41Sopenharmony_ci } catch (error) { 1991cb0ef41Sopenharmony_ci process.nextTick(() => { throw error; }); 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci })(); 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci killChild() { 2051cb0ef41Sopenharmony_ci this.client.reset(); 2061cb0ef41Sopenharmony_ci if (this.child) { 2071cb0ef41Sopenharmony_ci this.child.kill(); 2081cb0ef41Sopenharmony_ci this.child = null; 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci async run() { 2131cb0ef41Sopenharmony_ci this.killChild(); 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci const { 0: child, 1: port, 2: host } = await this._runScript(); 2161cb0ef41Sopenharmony_ci this.child = child; 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci this.print(`connecting to ${host}:${port} ..`, false); 2191cb0ef41Sopenharmony_ci for (let attempt = 0; attempt < 5; attempt++) { 2201cb0ef41Sopenharmony_ci debuglog('connection attempt #%d', attempt); 2211cb0ef41Sopenharmony_ci this.stdout.write('.'); 2221cb0ef41Sopenharmony_ci try { 2231cb0ef41Sopenharmony_ci await this.client.connect(port, host); 2241cb0ef41Sopenharmony_ci debuglog('connection established'); 2251cb0ef41Sopenharmony_ci this.stdout.write(' ok\n'); 2261cb0ef41Sopenharmony_ci return; 2271cb0ef41Sopenharmony_ci } catch (error) { 2281cb0ef41Sopenharmony_ci debuglog('connect failed', error); 2291cb0ef41Sopenharmony_ci await pSetTimeout(1000); 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci this.stdout.write(' failed to connect, please retry\n'); 2331cb0ef41Sopenharmony_ci process.exit(1); 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci clearLine() { 2371cb0ef41Sopenharmony_ci if (this.stdout.isTTY) { 2381cb0ef41Sopenharmony_ci this.stdout.cursorTo(0); 2391cb0ef41Sopenharmony_ci this.stdout.clearLine(1); 2401cb0ef41Sopenharmony_ci } else { 2411cb0ef41Sopenharmony_ci this.stdout.write('\b'); 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci print(text, appendNewline = false) { 2461cb0ef41Sopenharmony_ci this.clearLine(); 2471cb0ef41Sopenharmony_ci this.stdout.write(appendNewline ? `${text}\n` : text); 2481cb0ef41Sopenharmony_ci } 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci #stdioBuffers = { stdout: '', stderr: '' }; 2511cb0ef41Sopenharmony_ci childPrint(text, which) { 2521cb0ef41Sopenharmony_ci const lines = RegExpPrototypeSymbolSplit( 2531cb0ef41Sopenharmony_ci /\r\n|\r|\n/g, 2541cb0ef41Sopenharmony_ci this.#stdioBuffers[which] + text); 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci this.#stdioBuffers[which] = ''; 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci if (lines[lines.length - 1] !== '') { 2591cb0ef41Sopenharmony_ci this.#stdioBuffers[which] = ArrayPrototypePop(lines); 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci const textToPrint = ArrayPrototypeJoin( 2631cb0ef41Sopenharmony_ci ArrayPrototypeMap(lines, (chunk) => `< ${chunk}`), 2641cb0ef41Sopenharmony_ci '\n'); 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci if (lines.length) { 2671cb0ef41Sopenharmony_ci this.print(textToPrint, true); 2681cb0ef41Sopenharmony_ci if (!this.paused) { 2691cb0ef41Sopenharmony_ci this.repl.displayPrompt(true); 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci } 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci if (StringPrototypeEndsWith( 2741cb0ef41Sopenharmony_ci textToPrint, 2751cb0ef41Sopenharmony_ci 'Waiting for the debugger to disconnect...\n', 2761cb0ef41Sopenharmony_ci )) { 2771cb0ef41Sopenharmony_ci this.killChild(); 2781cb0ef41Sopenharmony_ci } 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci} 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_cifunction parseArgv(args) { 2831cb0ef41Sopenharmony_ci const target = ArrayPrototypeShift(args); 2841cb0ef41Sopenharmony_ci let host = '127.0.0.1'; 2851cb0ef41Sopenharmony_ci let port = 9229; 2861cb0ef41Sopenharmony_ci let isRemote = false; 2871cb0ef41Sopenharmony_ci let script = target; 2881cb0ef41Sopenharmony_ci let scriptArgs = args; 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci const hostMatch = RegExpPrototypeExec(/^([^:]+):(\d+)$/, target); 2911cb0ef41Sopenharmony_ci const portMatch = RegExpPrototypeExec(/^--port=(\d+)$/, target); 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci if (hostMatch) { 2941cb0ef41Sopenharmony_ci // Connecting to remote debugger 2951cb0ef41Sopenharmony_ci host = hostMatch[1]; 2961cb0ef41Sopenharmony_ci port = Number(hostMatch[2]); 2971cb0ef41Sopenharmony_ci isRemote = true; 2981cb0ef41Sopenharmony_ci script = null; 2991cb0ef41Sopenharmony_ci } else if (portMatch) { 3001cb0ef41Sopenharmony_ci // Start on custom port 3011cb0ef41Sopenharmony_ci port = Number(portMatch[1]); 3021cb0ef41Sopenharmony_ci script = args[0]; 3031cb0ef41Sopenharmony_ci scriptArgs = ArrayPrototypeSlice(args, 1); 3041cb0ef41Sopenharmony_ci } else if (args.length === 1 && RegExpPrototypeExec(/^\d+$/, args[0]) !== null && 3051cb0ef41Sopenharmony_ci target === '-p') { 3061cb0ef41Sopenharmony_ci // Start debugger against a given pid 3071cb0ef41Sopenharmony_ci const pid = Number(args[0]); 3081cb0ef41Sopenharmony_ci try { 3091cb0ef41Sopenharmony_ci process._debugProcess(pid); 3101cb0ef41Sopenharmony_ci } catch (e) { 3111cb0ef41Sopenharmony_ci if (e.code === 'ESRCH') { 3121cb0ef41Sopenharmony_ci process.stderr.write(`Target process: ${pid} doesn't exist.\n`); 3131cb0ef41Sopenharmony_ci process.exit(1); 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci throw e; 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci script = null; 3181cb0ef41Sopenharmony_ci isRemote = true; 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci return { 3221cb0ef41Sopenharmony_ci host, port, isRemote, script, scriptArgs, 3231cb0ef41Sopenharmony_ci }; 3241cb0ef41Sopenharmony_ci} 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_cifunction startInspect(argv = ArrayPrototypeSlice(process.argv, 2), 3271cb0ef41Sopenharmony_ci stdin = process.stdin, 3281cb0ef41Sopenharmony_ci stdout = process.stdout) { 3291cb0ef41Sopenharmony_ci if (argv.length < 1) { 3301cb0ef41Sopenharmony_ci const invokedAs = `${process.argv0} ${process.argv[1]}`; 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci process.stderr.write(`Usage: ${invokedAs} script.js\n` + 3331cb0ef41Sopenharmony_ci ` ${invokedAs} <host>:<port>\n` + 3341cb0ef41Sopenharmony_ci ` ${invokedAs} --port=<port> Use 0 for random port assignment\n` + 3351cb0ef41Sopenharmony_ci ` ${invokedAs} -p <pid>\n`); 3361cb0ef41Sopenharmony_ci process.exit(1); 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci const options = parseArgv(argv); 3401cb0ef41Sopenharmony_ci const inspector = new NodeInspector(options, stdin, stdout); 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ci stdin.resume(); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci function handleUnexpectedError(e) { 3451cb0ef41Sopenharmony_ci if (e.code !== 'ERR_DEBUGGER_STARTUP_ERROR') { 3461cb0ef41Sopenharmony_ci process.stderr.write('There was an internal error in Node.js. ' + 3471cb0ef41Sopenharmony_ci 'Please report this bug.\n' + 3481cb0ef41Sopenharmony_ci `${e.message}\n${e.stack}\n`); 3491cb0ef41Sopenharmony_ci } else { 3501cb0ef41Sopenharmony_ci process.stderr.write(e.message); 3511cb0ef41Sopenharmony_ci process.stderr.write('\n'); 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci if (inspector.child) inspector.child.kill(); 3541cb0ef41Sopenharmony_ci process.exit(1); 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci process.on('uncaughtException', handleUnexpectedError); 3581cb0ef41Sopenharmony_ci} 3591cb0ef41Sopenharmony_ciexports.start = startInspect; 360