| 472 | }; |
| 473 | |
| 474 | function launch() { |
| 475 | const server = net.createServer(target => { |
| 476 | connections++; |
| 477 | target.setEncoding("utf8"); |
| 478 | target.on('error', (e) => { |
| 479 | if (target.machine?.title) |
| 480 | console.log(`#xsbug-log socket error for "${target.machine.title}": ${e.message}`); |
| 481 | }); |
| 482 | target.on('close', () => { |
| 483 | if (target.machine) { |
| 484 | if (target.machine.title && ("mcsim" !== target.machine.title)) |
| 485 | target.machine.print(`#xsbug-log disconnected from "${target.machine.title}"`); |
| 486 | |
| 487 | const isDyingActive = (xsdbRouter.activeThreadId === target.machine.id); |
| 488 | |
| 489 | const idx = xsdbRouter.machines.indexOf(target.machine); |
| 490 | if (idx !== -1) xsdbRouter.machines[idx] = null; |
| 491 | target.machine = null; |
| 492 | |
| 493 | if (isDyingActive) { |
| 494 | xsdbRouter.activeThreadId = 0; |
| 495 | const fallback = xsdbRouter.machines.find(m => m && !xsdbRouter.isHidden(m)); |
| 496 | if (fallback) |
| 497 | xsdbRouter.activeThreadId = fallback.id; |
| 498 | else if (xsdbRouter.rl) |
| 499 | xsdbRouter.rl.prompt(true); |
| 500 | } |
| 501 | |
| 502 | if (!xsdbRouter.machines.some(m => m)) |
| 503 | xsdbRouter.nextThreadId = 1; |
| 504 | } |
| 505 | |
| 506 | if ((0 === --connections) && autoexit) |
| 507 | process.exit(0); |
| 508 | }); |
| 509 | |
| 510 | target.machine = xsdbRouter.addMachine(target); |
| 511 | }); |
| 512 | |
| 513 | server.listen(portIn, () => { |
| 514 | console.log(`xsdb listening on port ${portIn}. Type "quit" to exit.`); |
| 515 | }); |
| 516 | |
| 517 | let args = process.argv.slice(2); |
| 518 | if (args.length === 0) { |
| 519 | console.log("xsdb: no command line arguments. Waiting for connection."); |
| 520 | return; |
| 521 | } |
| 522 | |
| 523 | // Intercept OS-detaching execution hooks |
| 524 | if (args.length >= 2 && args[0] === 'open' && (args[1] === '-a' || args[1] === '-W')) { |
| 525 | args = args.slice(2); |
| 526 | // Remap macOS .app bundles to their internal WindowServer binary |
| 527 | if (args[0] && args[0].endsWith('.app')) { |
| 528 | const appName = args[0].split('/').pop().replace('.app', ''); |
| 529 | let binaryPath = `${args[0]}/Contents/MacOS/${appName}`; |
| 530 | if (!fs.existsSync(binaryPath)) { |
| 531 | binaryPath = `${args[0]}/Contents/MacOS/main`; |