@lvce-editor/pty-host 8.8.0 → 8.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ptyHostMain.js +217 -109
- package/package.json +1 -1
package/dist/ptyHostMain.js
CHANGED
|
@@ -1378,88 +1378,6 @@ const NodeWebSocketRpcClient = {
|
|
|
1378
1378
|
create: create$2
|
|
1379
1379
|
};
|
|
1380
1380
|
|
|
1381
|
-
const METHODS_THAT_REQUIRE_SOCKET = new Set(['Terminal.create']);
|
|
1382
|
-
const requiresSocket = method => {
|
|
1383
|
-
return METHODS_THAT_REQUIRE_SOCKET.has(method);
|
|
1384
|
-
};
|
|
1385
|
-
|
|
1386
|
-
const handleElectronMessagePort = async messagePort => {
|
|
1387
|
-
object(messagePort);
|
|
1388
|
-
await create$5({
|
|
1389
|
-
commandMap: {},
|
|
1390
|
-
messagePort,
|
|
1391
|
-
requiresSocket: requiresSocket
|
|
1392
|
-
});
|
|
1393
|
-
};
|
|
1394
|
-
|
|
1395
|
-
const NodeWorker = 1;
|
|
1396
|
-
const NodeForkedProcess = 2;
|
|
1397
|
-
const WebSocket = 3;
|
|
1398
|
-
const ElectronUtilityProcess = 4;
|
|
1399
|
-
const ElectronMessagePort = 5;
|
|
1400
|
-
const NodeMessagePort = 6;
|
|
1401
|
-
const Auto = () => {
|
|
1402
|
-
const {
|
|
1403
|
-
argv
|
|
1404
|
-
} = process;
|
|
1405
|
-
if (argv.includes('--ipc-type=node-worker')) {
|
|
1406
|
-
return NodeWorker;
|
|
1407
|
-
}
|
|
1408
|
-
if (argv.includes('--ipc-type=node-forked-process')) {
|
|
1409
|
-
return NodeForkedProcess;
|
|
1410
|
-
}
|
|
1411
|
-
if (argv.includes('--ipc-type=websocket')) {
|
|
1412
|
-
return WebSocket;
|
|
1413
|
-
}
|
|
1414
|
-
if (argv.includes('--ipc-type=electron-utility-process')) {
|
|
1415
|
-
return ElectronUtilityProcess;
|
|
1416
|
-
}
|
|
1417
|
-
throw new Error(`[pty-host] unknown ipc type`);
|
|
1418
|
-
};
|
|
1419
|
-
|
|
1420
|
-
const getModule = method => {
|
|
1421
|
-
switch (method) {
|
|
1422
|
-
case ElectronMessagePort:
|
|
1423
|
-
return ElectronMessagePortRpcClient;
|
|
1424
|
-
case ElectronUtilityProcess:
|
|
1425
|
-
return ElectronUtilityProcessRpcClient;
|
|
1426
|
-
case NodeForkedProcess:
|
|
1427
|
-
return NodeForkedProcessRpcClient;
|
|
1428
|
-
case WebSocket:
|
|
1429
|
-
return NodeWebSocketRpcClient;
|
|
1430
|
-
default:
|
|
1431
|
-
throw new Error('unexpected ipc type');
|
|
1432
|
-
}
|
|
1433
|
-
};
|
|
1434
|
-
|
|
1435
|
-
const listen$1 = async ({
|
|
1436
|
-
method,
|
|
1437
|
-
...params
|
|
1438
|
-
}) => {
|
|
1439
|
-
const module = getModule(method);
|
|
1440
|
-
// @ts-ignore
|
|
1441
|
-
const rpc = await module.create(params);
|
|
1442
|
-
return rpc;
|
|
1443
|
-
};
|
|
1444
|
-
|
|
1445
|
-
const handleNodeMessagePort = async messagePort => {
|
|
1446
|
-
await listen$1({
|
|
1447
|
-
messagePort,
|
|
1448
|
-
method: NodeMessagePort
|
|
1449
|
-
});
|
|
1450
|
-
};
|
|
1451
|
-
|
|
1452
|
-
const handleWebSocket = async (handle, request) => {
|
|
1453
|
-
object(handle);
|
|
1454
|
-
object(request);
|
|
1455
|
-
await create$2({
|
|
1456
|
-
commandMap: {},
|
|
1457
|
-
handle,
|
|
1458
|
-
request,
|
|
1459
|
-
requiresSocket: requiresSocket
|
|
1460
|
-
});
|
|
1461
|
-
};
|
|
1462
|
-
|
|
1463
1381
|
class DataEvent extends Event {
|
|
1464
1382
|
constructor(data) {
|
|
1465
1383
|
super('data');
|
|
@@ -1539,63 +1457,251 @@ const create$1 = async ({
|
|
|
1539
1457
|
}
|
|
1540
1458
|
};
|
|
1541
1459
|
|
|
1542
|
-
const
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1460
|
+
const connections$1 = new WeakMap();
|
|
1461
|
+
const set = (ipc, id, pty) => {
|
|
1462
|
+
let terminals = connections$1.get(ipc);
|
|
1463
|
+
if (!terminals) {
|
|
1464
|
+
terminals = new Map();
|
|
1465
|
+
connections$1.set(ipc, terminals);
|
|
1466
|
+
}
|
|
1467
|
+
terminals.set(id, pty);
|
|
1547
1468
|
};
|
|
1548
|
-
const get = id =>
|
|
1549
|
-
|
|
1469
|
+
const get = (ipc, id) => connections$1.get(ipc)?.get(id);
|
|
1470
|
+
const remove = (ipc, id) => {
|
|
1471
|
+
connections$1.get(ipc)?.delete(id);
|
|
1550
1472
|
};
|
|
1551
|
-
|
|
1552
|
-
|
|
1473
|
+
|
|
1474
|
+
const connections = new WeakMap();
|
|
1475
|
+
const cleanup = new WeakMap();
|
|
1476
|
+
const closedConnections = new WeakSet();
|
|
1477
|
+
const disposeConnection = ipc => {
|
|
1478
|
+
closedConnections.add(ipc);
|
|
1479
|
+
const entries = connections.get(ipc);
|
|
1480
|
+
connections.delete(ipc);
|
|
1481
|
+
if (!entries) return;
|
|
1482
|
+
for (const entry of entries) {
|
|
1483
|
+
entry.closed = true;
|
|
1484
|
+
if (entry.pty) {
|
|
1485
|
+
cleanup.get(entry.pty)?.();
|
|
1486
|
+
entry.pty.dispose();
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1553
1489
|
};
|
|
1554
1490
|
|
|
1555
1491
|
// TODO maybe merge pty and pty controller
|
|
1556
|
-
const
|
|
1492
|
+
const createWithDependencies = async (ipc, id, cwd, command, args, createPty) => {
|
|
1557
1493
|
number(id);
|
|
1558
1494
|
string(cwd);
|
|
1559
1495
|
string(command);
|
|
1560
1496
|
array(args);
|
|
1561
1497
|
object(ipc);
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
}
|
|
1498
|
+
if (closedConnections.has(ipc)) throw new Error('Terminal connection closed');
|
|
1499
|
+
let entries = connections.get(ipc);
|
|
1500
|
+
if (!entries) {
|
|
1501
|
+
entries = new Set();
|
|
1502
|
+
connections.set(ipc, entries);
|
|
1503
|
+
}
|
|
1504
|
+
const entry = {
|
|
1505
|
+
closed: false
|
|
1506
|
+
};
|
|
1507
|
+
entries.add(entry);
|
|
1508
|
+
let pty;
|
|
1509
|
+
try {
|
|
1510
|
+
pty = await createPty({
|
|
1511
|
+
args,
|
|
1512
|
+
command,
|
|
1513
|
+
cwd
|
|
1514
|
+
});
|
|
1515
|
+
} catch (error) {
|
|
1516
|
+
entries.delete(entry);
|
|
1517
|
+
throw error;
|
|
1518
|
+
}
|
|
1519
|
+
entry.pty = pty;
|
|
1520
|
+
if (entry.closed) {
|
|
1521
|
+
pty.dispose();
|
|
1522
|
+
throw new Error('Terminal connection closed');
|
|
1523
|
+
}
|
|
1568
1524
|
const handleData = event => {
|
|
1525
|
+
if (entry.closed) return;
|
|
1569
1526
|
ipc.send({
|
|
1570
1527
|
jsonrpc: '2.0',
|
|
1571
1528
|
method: 'Viewlet.send',
|
|
1572
1529
|
params: [id, 'handleData', event.data]
|
|
1573
1530
|
});
|
|
1574
1531
|
};
|
|
1532
|
+
const handleExit = event => {
|
|
1533
|
+
entries.delete(entry);
|
|
1534
|
+
if (get(ipc, id) === pty) remove(ipc, id);
|
|
1535
|
+
if (entry.closed) return;
|
|
1536
|
+
ipc.send({
|
|
1537
|
+
jsonrpc: '2.0',
|
|
1538
|
+
method: 'Viewlet.send',
|
|
1539
|
+
params: [id, 'handleExit', event.data]
|
|
1540
|
+
});
|
|
1541
|
+
};
|
|
1542
|
+
cleanup.set(pty, () => {
|
|
1543
|
+
entry.closed = true;
|
|
1544
|
+
entries.delete(entry);
|
|
1545
|
+
pty.removeEventListener('data', handleData);
|
|
1546
|
+
pty.removeEventListener('exit', handleExit);
|
|
1547
|
+
if (get(ipc, id) === pty) remove(ipc, id);
|
|
1548
|
+
cleanup.delete(pty);
|
|
1549
|
+
});
|
|
1575
1550
|
pty.addEventListener('data', handleData);
|
|
1576
|
-
|
|
1551
|
+
pty.addEventListener('exit', handleExit, {
|
|
1552
|
+
once: true
|
|
1553
|
+
});
|
|
1554
|
+
set(ipc, id, pty);
|
|
1555
|
+
};
|
|
1556
|
+
const create = (ipc, id, cwd, command, args) => {
|
|
1557
|
+
return createWithDependencies(ipc, id, cwd, command, args, create$1);
|
|
1577
1558
|
};
|
|
1578
|
-
const write = (id, data) => {
|
|
1579
|
-
const pty = get(id);
|
|
1559
|
+
const write = (ipc, id, data) => {
|
|
1560
|
+
const pty = get(ipc, id);
|
|
1580
1561
|
if (!pty) {
|
|
1581
1562
|
throw new Error(`pty ${id} not found`);
|
|
1582
1563
|
}
|
|
1583
1564
|
pty.write(data);
|
|
1584
1565
|
};
|
|
1585
|
-
const resize = (id, columns, rows) => {
|
|
1586
|
-
const pty = get(id);
|
|
1566
|
+
const resize = (ipc, id, columns, rows) => {
|
|
1567
|
+
const pty = get(ipc, id);
|
|
1587
1568
|
if (!pty) {
|
|
1588
1569
|
throw new Error(`pty ${id} not found`);
|
|
1589
1570
|
}
|
|
1590
1571
|
pty.resize(columns, rows);
|
|
1591
1572
|
};
|
|
1592
|
-
const dispose = id => {
|
|
1593
|
-
const pty = get(id);
|
|
1573
|
+
const dispose = (ipc, id) => {
|
|
1574
|
+
const pty = get(ipc, id);
|
|
1594
1575
|
if (!pty) {
|
|
1595
|
-
|
|
1576
|
+
return;
|
|
1596
1577
|
}
|
|
1578
|
+
cleanup.get(pty)?.();
|
|
1597
1579
|
pty.dispose();
|
|
1598
|
-
remove(id);
|
|
1580
|
+
if (get(ipc, id) === pty) remove(ipc, id);
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1583
|
+
const ready = Promise.withResolvers();
|
|
1584
|
+
const state$1 = {};
|
|
1585
|
+
const setParent = rpc => {
|
|
1586
|
+
state$1.parent = rpc;
|
|
1587
|
+
ready.resolve();
|
|
1588
|
+
};
|
|
1589
|
+
const release = async id => {
|
|
1590
|
+
if (!state$1.parent) await ready.promise;
|
|
1591
|
+
state$1.parent.send('PtyHost.release', id);
|
|
1592
|
+
};
|
|
1593
|
+
const connect = async (handle, id, create) => {
|
|
1594
|
+
let closed = false;
|
|
1595
|
+
let rpc;
|
|
1596
|
+
const onClose = () => {
|
|
1597
|
+
if (closed) return;
|
|
1598
|
+
closed = true;
|
|
1599
|
+
handle.off('close', onClose);
|
|
1600
|
+
try {
|
|
1601
|
+
if (rpc) disposeConnection(rpc.ipc);
|
|
1602
|
+
} finally {
|
|
1603
|
+
if (id !== undefined) void release(id);
|
|
1604
|
+
}
|
|
1605
|
+
};
|
|
1606
|
+
handle.on('close', onClose);
|
|
1607
|
+
try {
|
|
1608
|
+
if (handle.destroyed) throw new Error('Terminal connection closed');
|
|
1609
|
+
rpc = await create();
|
|
1610
|
+
if (closed) {
|
|
1611
|
+
disposeConnection(rpc.ipc);
|
|
1612
|
+
await rpc.dispose();
|
|
1613
|
+
}
|
|
1614
|
+
} catch (error) {
|
|
1615
|
+
onClose();
|
|
1616
|
+
handle.destroy?.();
|
|
1617
|
+
handle.close?.();
|
|
1618
|
+
throw error;
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
|
|
1622
|
+
const METHODS_THAT_REQUIRE_SOCKET = new Set(['Terminal.create', 'Terminal.write', 'Terminal.resize', 'Terminal.dispose']);
|
|
1623
|
+
const requiresSocket = method => {
|
|
1624
|
+
return METHODS_THAT_REQUIRE_SOCKET.has(method);
|
|
1625
|
+
};
|
|
1626
|
+
|
|
1627
|
+
const handleElectronMessagePort = async (messagePort, connectionId) => {
|
|
1628
|
+
object(messagePort);
|
|
1629
|
+
await connect(messagePort, connectionId, () => create$5({
|
|
1630
|
+
commandMap: {},
|
|
1631
|
+
messagePort,
|
|
1632
|
+
requiresSocket: requiresSocket
|
|
1633
|
+
}));
|
|
1634
|
+
};
|
|
1635
|
+
|
|
1636
|
+
const NodeWorker = 1;
|
|
1637
|
+
const NodeForkedProcess = 2;
|
|
1638
|
+
const WebSocket = 3;
|
|
1639
|
+
const ElectronUtilityProcess = 4;
|
|
1640
|
+
const ElectronMessagePort = 5;
|
|
1641
|
+
const NodeMessagePort = 6;
|
|
1642
|
+
const Auto = () => {
|
|
1643
|
+
const {
|
|
1644
|
+
argv
|
|
1645
|
+
} = process;
|
|
1646
|
+
if (argv.includes('--ipc-type=node-worker')) {
|
|
1647
|
+
return NodeWorker;
|
|
1648
|
+
}
|
|
1649
|
+
if (argv.includes('--ipc-type=node-forked-process')) {
|
|
1650
|
+
return NodeForkedProcess;
|
|
1651
|
+
}
|
|
1652
|
+
if (argv.includes('--ipc-type=websocket')) {
|
|
1653
|
+
return WebSocket;
|
|
1654
|
+
}
|
|
1655
|
+
if (argv.includes('--ipc-type=electron-utility-process')) {
|
|
1656
|
+
return ElectronUtilityProcess;
|
|
1657
|
+
}
|
|
1658
|
+
throw new Error(`[pty-host] unknown ipc type`);
|
|
1659
|
+
};
|
|
1660
|
+
|
|
1661
|
+
const getModule = method => {
|
|
1662
|
+
switch (method) {
|
|
1663
|
+
case ElectronMessagePort:
|
|
1664
|
+
return ElectronMessagePortRpcClient;
|
|
1665
|
+
case ElectronUtilityProcess:
|
|
1666
|
+
return ElectronUtilityProcessRpcClient;
|
|
1667
|
+
case NodeForkedProcess:
|
|
1668
|
+
return NodeForkedProcessRpcClient;
|
|
1669
|
+
case WebSocket:
|
|
1670
|
+
return NodeWebSocketRpcClient;
|
|
1671
|
+
default:
|
|
1672
|
+
throw new Error('unexpected ipc type');
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
|
|
1676
|
+
const listen$1 = async ({
|
|
1677
|
+
method,
|
|
1678
|
+
...params
|
|
1679
|
+
}) => {
|
|
1680
|
+
const module = getModule(method);
|
|
1681
|
+
// @ts-ignore
|
|
1682
|
+
const rpc = await module.create(params);
|
|
1683
|
+
if (params.requiresSocket) {
|
|
1684
|
+
rpc.ipc.requiresSocket = params.requiresSocket;
|
|
1685
|
+
}
|
|
1686
|
+
return rpc;
|
|
1687
|
+
};
|
|
1688
|
+
|
|
1689
|
+
const handleNodeMessagePort = async messagePort => {
|
|
1690
|
+
await listen$1({
|
|
1691
|
+
messagePort,
|
|
1692
|
+
method: NodeMessagePort
|
|
1693
|
+
});
|
|
1694
|
+
};
|
|
1695
|
+
|
|
1696
|
+
const handleWebSocket = async (handle, request, connectionId) => {
|
|
1697
|
+
object(handle);
|
|
1698
|
+
object(request);
|
|
1699
|
+
await connect(handle, connectionId, () => create$2({
|
|
1700
|
+
commandMap: {},
|
|
1701
|
+
handle,
|
|
1702
|
+
request,
|
|
1703
|
+
requiresSocket: requiresSocket
|
|
1704
|
+
}));
|
|
1599
1705
|
};
|
|
1600
1706
|
|
|
1601
1707
|
const HandleElectronMessagePort = 'HandleElectronMessagePort.handleElectronMessagePort';
|
|
@@ -1619,9 +1725,11 @@ const commandMap = {
|
|
|
1619
1725
|
};
|
|
1620
1726
|
|
|
1621
1727
|
const listen = async () => {
|
|
1622
|
-
await listen$1({
|
|
1623
|
-
method: Auto()
|
|
1728
|
+
const rpc = await listen$1({
|
|
1729
|
+
method: Auto(),
|
|
1730
|
+
requiresSocket: requiresSocket
|
|
1624
1731
|
});
|
|
1732
|
+
setParent(rpc);
|
|
1625
1733
|
};
|
|
1626
1734
|
|
|
1627
1735
|
const NewLine$1 = '\n';
|