@lvce-editor/source-control-worker 3.14.0 → 3.15.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.
@@ -145,7 +145,6 @@ const walkValue = (value, transferrables, isTransferrable) => {
145
145
  for (const property of Object.values(value)) {
146
146
  walkValue(property, transferrables, isTransferrable);
147
147
  }
148
- return;
149
148
  }
150
149
  };
151
150
  const getTransferrables = value => {
@@ -299,7 +298,14 @@ class IpcError extends VError {
299
298
  const cause = new Error(message);
300
299
  // @ts-ignore
301
300
  cause.code = code;
302
- cause.stack = stack;
301
+ if (stack) {
302
+ Object.defineProperty(cause, 'stack', {
303
+ configurable: true,
304
+ enumerable: false,
305
+ value: stack,
306
+ writable: true
307
+ });
308
+ }
303
309
  super(cause, betterMessage);
304
310
  } else {
305
311
  super(betterMessage);
@@ -1122,12 +1128,226 @@ const create$1 = rpcId => {
1122
1128
  };
1123
1129
  };
1124
1130
 
1131
+ const None$1 = 'none';
1132
+ const ToolBar = 'toolbar';
1133
+ const Tree$1 = 'tree';
1134
+ const TreeItem$1 = 'treeitem';
1135
+
1136
+ const Badge = 'Badge';
1137
+ const MaskIcon = 'MaskIcon';
1138
+ const SourceControlBadge = 'SourceControlBadge';
1139
+
1140
+ const Directory = 3;
1141
+ const DirectoryExpanded = 4;
1142
+ const File = 7;
1143
+
1144
+ const Audio = 0;
1145
+ const Button$2 = 1;
1146
+ const Col = 2;
1147
+ const ColGroup = 3;
1148
+ const Div = 4;
1149
+ const H1 = 5;
1150
+ const Input = 6;
1151
+ const Kbd = 7;
1152
+ const Span = 8;
1153
+ const Table = 9;
1154
+ const TBody = 10;
1155
+ const Td = 11;
1156
+ const Text = 12;
1157
+ const Th = 13;
1158
+ const THead = 14;
1159
+ const Tr = 15;
1160
+ const I = 16;
1161
+ const Img = 17;
1162
+ const Root = 0;
1163
+ const Ins = 20;
1164
+ const Del = 21;
1165
+ const H2 = 22;
1166
+ const H3 = 23;
1167
+ const H4 = 24;
1168
+ const H5 = 25;
1169
+ const H6 = 26;
1170
+ const Article = 27;
1171
+ const Aside = 28;
1172
+ const Footer = 29;
1173
+ const Header = 30;
1174
+ const Nav = 40;
1175
+ const Section = 41;
1176
+ const Search = 42;
1177
+ const Dd = 43;
1178
+ const Dl = 44;
1179
+ const Figcaption = 45;
1180
+ const Figure = 46;
1181
+ const Hr = 47;
1182
+ const Li = 48;
1183
+ const Ol = 49;
1184
+ const P = 50;
1185
+ const Pre = 51;
1186
+ const A = 53;
1187
+ const Abbr = 54;
1188
+ const Br = 55;
1189
+ const Cite = 56;
1190
+ const Data = 57;
1191
+ const Time = 58;
1192
+ const Tfoot = 59;
1193
+ const Ul = 60;
1194
+ const Video = 61;
1195
+ const TextArea = 62;
1196
+ const Select = 63;
1197
+ const Option = 64;
1198
+ const Code = 65;
1199
+ const Label$1 = 66;
1200
+ const Dt = 67;
1201
+ const Iframe = 68;
1202
+ const Main = 69;
1203
+ const Strong = 70;
1204
+ const Em = 71;
1205
+ const Style = 72;
1206
+ const Html = 73;
1207
+ const Head = 74;
1208
+ const Title = 75;
1209
+ const Meta = 76;
1210
+ const Canvas = 77;
1211
+ const Form = 78;
1212
+ const BlockQuote = 79;
1213
+ const Quote = 80;
1214
+ const Circle = 81;
1215
+ const Defs = 82;
1216
+ const Ellipse = 83;
1217
+ const G = 84;
1218
+ const Line = 85;
1219
+ const Path = 86;
1220
+ const Polygon = 87;
1221
+ const Polyline = 88;
1222
+ const Rect = 89;
1223
+ const Svg = 90;
1224
+ const Use = 91;
1225
+ const Reference = 100;
1226
+
1227
+ const VirtualDomElements = {
1228
+ __proto__: null,
1229
+ A,
1230
+ Abbr,
1231
+ Article,
1232
+ Aside,
1233
+ Audio,
1234
+ BlockQuote,
1235
+ Br,
1236
+ Button: Button$2,
1237
+ Canvas,
1238
+ Circle,
1239
+ Cite,
1240
+ Code,
1241
+ Col,
1242
+ ColGroup,
1243
+ Data,
1244
+ Dd,
1245
+ Defs,
1246
+ Del,
1247
+ Div,
1248
+ Dl,
1249
+ Dt,
1250
+ Ellipse,
1251
+ Em,
1252
+ Figcaption,
1253
+ Figure,
1254
+ Footer,
1255
+ Form,
1256
+ G,
1257
+ H1,
1258
+ H2,
1259
+ H3,
1260
+ H4,
1261
+ H5,
1262
+ H6,
1263
+ Head,
1264
+ Header,
1265
+ Hr,
1266
+ Html,
1267
+ I,
1268
+ Iframe,
1269
+ Img,
1270
+ Input,
1271
+ Ins,
1272
+ Kbd,
1273
+ Label: Label$1,
1274
+ Li,
1275
+ Line,
1276
+ Main,
1277
+ Meta,
1278
+ Nav,
1279
+ Ol,
1280
+ Option,
1281
+ P,
1282
+ Path,
1283
+ Polygon,
1284
+ Polyline,
1285
+ Pre,
1286
+ Quote,
1287
+ Rect,
1288
+ Reference,
1289
+ Root,
1290
+ Search,
1291
+ Section,
1292
+ Select,
1293
+ Span,
1294
+ Strong,
1295
+ Style,
1296
+ Svg,
1297
+ TBody,
1298
+ THead,
1299
+ Table,
1300
+ Td,
1301
+ Text,
1302
+ TextArea,
1303
+ Tfoot,
1304
+ Th,
1305
+ Time,
1306
+ Title,
1307
+ Tr,
1308
+ Ul,
1309
+ Use,
1310
+ Video
1311
+ };
1312
+
1313
+ const Button$1 = 'event.button';
1314
+ const ClientX = 'event.clientX';
1315
+ const ClientY = 'event.clientY';
1316
+ const DeltaMode = 'event.deltaMode';
1317
+ const DeltaY = 'event.deltaY';
1318
+ const TargetName = 'event.target.name';
1319
+ const TargetValue = 'event.target.value';
1320
+
1321
+ const Enter = 3;
1322
+
1323
+ const User = 1;
1324
+ const Script = 2;
1325
+
1326
+ const CtrlCmd = 1 << 11 >>> 0;
1327
+
1328
+ const SourceControl$1 = 22;
1329
+
1330
+ const None = 0;
1331
+
1332
+ const Web = 1;
1333
+ const Electron = 2;
1334
+ const Remote = 3;
1335
+
1125
1336
  const ExtensionHostWorker = 44;
1126
1337
  const ExtensionManagementWorker = 9006;
1127
1338
  const IconThemeWorker = 7009;
1128
1339
  const RendererProcess = 1670;
1129
1340
  const RendererWorker = 1;
1130
- const SourceControlWorker = 66;
1341
+
1342
+ const SetCss = 'Viewlet.setCss';
1343
+ const SetDom2 = 'Viewlet.setDom2';
1344
+ const SetFocusContext = 'Viewlet.setFocusContext';
1345
+ const SetValueByName = 'Viewlet.setValueByName';
1346
+
1347
+ const List$1 = 1;
1348
+ const Tree = 2;
1349
+
1350
+ const FocusSourceControlInput = 24;
1131
1351
 
1132
1352
  const {
1133
1353
  invoke: invoke$4,
@@ -1144,10 +1364,14 @@ const {
1144
1364
  set: set$4
1145
1365
  } = create$1(RendererProcess);
1146
1366
 
1367
+ const {
1368
+ set: set$3
1369
+ } = create$1(IconThemeWorker);
1370
+
1147
1371
  const {
1148
1372
  invoke: invoke$1,
1149
1373
  invokeAndTransfer,
1150
- set: set$3
1374
+ set: set$2
1151
1375
  } = create$1(RendererWorker);
1152
1376
  const showContextMenu2 = async (uid, menuId, x, y, args) => {
1153
1377
  number(uid);
@@ -1159,10 +1383,6 @@ const showContextMenu2 = async (uid, menuId, x, y, args) => {
1159
1383
  const readFile$1 = async uri => {
1160
1384
  return invoke$1('FileSystem.readFile', uri);
1161
1385
  };
1162
- const sendMessagePortToExtensionHostWorker$1 = async (port, rpcId = 0) => {
1163
- const command = 'HandleMessagePort.handleMessagePort2';
1164
- await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, rpcId);
1165
- };
1166
1386
  const activateByEvent$1 = (event, assetDir, platform) => {
1167
1387
  return invoke$1('ExtensionHostManagement.activateByEvent', event, assetDir, platform);
1168
1388
  };
@@ -1178,41 +1398,112 @@ const getPreference = async key => {
1178
1398
  return await invoke$1('Preferences.get', key);
1179
1399
  };
1180
1400
  const openUri$1 = async (uri, focus, options) => {
1181
- await invoke$1('Main.openUri', uri, focus, options);
1401
+ await invoke$1('Main.openUri', {
1402
+ ...options,
1403
+ focus,
1404
+ uri
1405
+ });
1182
1406
  };
1183
1407
 
1184
- const {
1185
- set: set$2
1186
- } = create$1(IconThemeWorker);
1187
-
1188
1408
  const toCommandId = key => {
1189
1409
  const dotIndex = key.indexOf('.');
1190
1410
  return key.slice(dotIndex + 1);
1191
1411
  };
1192
1412
  const create = () => {
1413
+ const commandQueues = new Map();
1414
+ const generations = Object.create(null);
1193
1415
  const states = Object.create(null);
1194
- const commandMapRef = {};
1416
+ const commandMapRef = Object.create(null);
1417
+ const commandsById = Object.create(null);
1418
+ const getGeneration = uid => generations[uid] || 0;
1419
+ const isCurrentGeneration = (uid, generation) => {
1420
+ return states[uid] !== undefined && getGeneration(uid) === generation;
1421
+ };
1422
+ const updateState = (uid, generation, fallbackState, updater) => {
1423
+ if (!isCurrentGeneration(uid, generation)) {
1424
+ return Promise.resolve(fallbackState);
1425
+ }
1426
+ const current = states[uid];
1427
+ const updatedState = updater(current.newState);
1428
+ if (updatedState !== current.newState) {
1429
+ states[uid] = {
1430
+ newState: updatedState,
1431
+ oldState: current.oldState,
1432
+ scheduledState: updatedState
1433
+ };
1434
+ }
1435
+ return Promise.resolve(updatedState);
1436
+ };
1437
+ const createAsyncCommandContext = (uid, generation) => {
1438
+ let latestState = states[uid].newState;
1439
+ return {
1440
+ getState: () => {
1441
+ if (isCurrentGeneration(uid, generation)) {
1442
+ latestState = states[uid].newState;
1443
+ }
1444
+ return latestState;
1445
+ },
1446
+ updateState: async updater => {
1447
+ latestState = await updateState(uid, generation, latestState, updater);
1448
+ return latestState;
1449
+ }
1450
+ };
1451
+ };
1452
+ const enqueueCommand = async (uid, command) => {
1453
+ const previous = commandQueues.get(uid) || Promise.resolve();
1454
+ const run = async () => {
1455
+ try {
1456
+ await previous;
1457
+ } catch {
1458
+ // The previous caller receives its error; later commands must still run.
1459
+ }
1460
+ await command();
1461
+ };
1462
+ const current = run();
1463
+ commandQueues.set(uid, current);
1464
+ try {
1465
+ await current;
1466
+ } finally {
1467
+ if (commandQueues.get(uid) === current) {
1468
+ commandQueues.delete(uid);
1469
+ }
1470
+ }
1471
+ };
1195
1472
  return {
1196
1473
  clear() {
1474
+ commandQueues.clear();
1197
1475
  for (const key of Object.keys(states)) {
1198
1476
  delete states[key];
1199
1477
  }
1200
1478
  },
1479
+ createDirectEventCommandMap(requestRender) {
1480
+ return {
1481
+ async 'Viewlet.executeViewletCommand'(uid, command, ...args) {
1482
+ const fn = commandsById[command];
1483
+ if (!fn) {
1484
+ throw new Error(`Viewlet command not found: ${command}`);
1485
+ }
1486
+ await fn(uid, ...args);
1487
+ await requestRender(uid);
1488
+ }
1489
+ };
1490
+ },
1201
1491
  diff(uid, modules, numbers) {
1202
1492
  const {
1203
- newState,
1204
- oldState
1493
+ oldState,
1494
+ scheduledState
1205
1495
  } = states[uid];
1206
1496
  const diffResult = [];
1207
1497
  for (let i = 0; i < modules.length; i++) {
1208
1498
  const fn = modules[i];
1209
- if (!fn(oldState, newState)) {
1499
+ if (!fn(oldState, scheduledState)) {
1210
1500
  diffResult.push(numbers[i]);
1211
1501
  }
1212
1502
  }
1213
1503
  return diffResult;
1214
1504
  },
1215
1505
  dispose(uid) {
1506
+ commandQueues.delete(uid);
1216
1507
  delete states[uid];
1217
1508
  },
1218
1509
  get(uid) {
@@ -1224,21 +1515,36 @@ const create = () => {
1224
1515
  return ids;
1225
1516
  },
1226
1517
  getKeys() {
1227
- return Object.keys(states).map(key => {
1228
- return Number.parseFloat(key);
1229
- });
1518
+ return Object.keys(states).map(Number);
1230
1519
  },
1231
1520
  registerCommands(commandMap) {
1232
1521
  Object.assign(commandMapRef, commandMap);
1522
+ for (const [key, fn] of Object.entries(commandMap)) {
1523
+ commandsById[toCommandId(key)] = fn;
1524
+ }
1233
1525
  },
1234
- set(uid, oldState, newState) {
1526
+ set(uid, oldState, newState, scheduledState) {
1527
+ const current = states[uid];
1528
+ if (!current || oldState === newState && newState !== current.newState) {
1529
+ generations[uid] = getGeneration(uid) + 1;
1530
+ }
1235
1531
  states[uid] = {
1236
1532
  newState,
1237
- oldState
1533
+ oldState,
1534
+ scheduledState: scheduledState ?? newState
1535
+ };
1536
+ },
1537
+ wrapAsyncCommand(fn) {
1538
+ const wrapped = async (uid, ...args) => {
1539
+ const generation = getGeneration(uid);
1540
+ const context = createAsyncCommandContext(uid, generation);
1541
+ await fn(context, ...args);
1238
1542
  };
1543
+ return wrapped;
1239
1544
  },
1240
1545
  wrapCommand(fn) {
1241
1546
  const wrapped = async (uid, ...args) => {
1547
+ const generation = getGeneration(uid);
1242
1548
  const {
1243
1549
  newState,
1244
1550
  oldState
@@ -1247,6 +1553,9 @@ const create = () => {
1247
1553
  if (oldState === newerState || newState === newerState) {
1248
1554
  return;
1249
1555
  }
1556
+ if (!isCurrentGeneration(uid, generation)) {
1557
+ return;
1558
+ }
1250
1559
  const latestOld = states[uid];
1251
1560
  const latestNew = {
1252
1561
  ...latestOld.newState,
@@ -1254,7 +1563,8 @@ const create = () => {
1254
1563
  };
1255
1564
  states[uid] = {
1256
1565
  newState: latestNew,
1257
- oldState: latestOld.oldState
1566
+ oldState: latestOld.oldState,
1567
+ scheduledState: latestNew
1258
1568
  };
1259
1569
  };
1260
1570
  return wrapped;
@@ -1270,6 +1580,7 @@ const create = () => {
1270
1580
  },
1271
1581
  wrapLoadContent(fn) {
1272
1582
  const wrapped = async (uid, ...args) => {
1583
+ const generation = getGeneration(uid);
1273
1584
  const {
1274
1585
  newState,
1275
1586
  oldState
@@ -1284,6 +1595,11 @@ const create = () => {
1284
1595
  error
1285
1596
  };
1286
1597
  }
1598
+ if (!isCurrentGeneration(uid, generation)) {
1599
+ return {
1600
+ error
1601
+ };
1602
+ }
1287
1603
  const latestOld = states[uid];
1288
1604
  const latestNew = {
1289
1605
  ...latestOld.newState,
@@ -1291,13 +1607,59 @@ const create = () => {
1291
1607
  };
1292
1608
  states[uid] = {
1293
1609
  newState: latestNew,
1294
- oldState: latestOld.oldState
1610
+ oldState: latestOld.oldState,
1611
+ scheduledState: latestNew
1295
1612
  };
1296
1613
  return {
1297
1614
  error
1298
1615
  };
1299
1616
  };
1300
1617
  return wrapped;
1618
+ },
1619
+ wrapSerialAsyncCommand(fn) {
1620
+ const wrapped = async (uid, ...args) => {
1621
+ await enqueueCommand(uid, async () => {
1622
+ if (!states[uid]) {
1623
+ return;
1624
+ }
1625
+ const generation = getGeneration(uid);
1626
+ const context = createAsyncCommandContext(uid, generation);
1627
+ await fn(context, ...args);
1628
+ });
1629
+ };
1630
+ return wrapped;
1631
+ },
1632
+ wrapSerialCommand(fn) {
1633
+ const wrapped = async (uid, ...args) => {
1634
+ await enqueueCommand(uid, async () => {
1635
+ if (!states[uid]) {
1636
+ return;
1637
+ }
1638
+ const generation = getGeneration(uid);
1639
+ const {
1640
+ newState,
1641
+ oldState
1642
+ } = states[uid];
1643
+ const newerState = await fn(newState, ...args);
1644
+ if (oldState === newerState || newState === newerState) {
1645
+ return;
1646
+ }
1647
+ if (!isCurrentGeneration(uid, generation)) {
1648
+ return;
1649
+ }
1650
+ const latestOld = states[uid];
1651
+ const latestNew = {
1652
+ ...latestOld.newState,
1653
+ ...newerState
1654
+ };
1655
+ states[uid] = {
1656
+ newState: latestNew,
1657
+ oldState: latestOld.oldState,
1658
+ scheduledState: latestNew
1659
+ };
1660
+ });
1661
+ };
1662
+ return wrapped;
1301
1663
  }
1302
1664
  };
1303
1665
  };
@@ -1305,60 +1667,6 @@ const terminate = () => {
1305
1667
  globalThis.close();
1306
1668
  };
1307
1669
 
1308
- const None$1 = 'none';
1309
- const ToolBar = 'toolbar';
1310
- const Tree$1 = 'tree';
1311
- const TreeItem$1 = 'treeitem';
1312
-
1313
- const Badge = 'Badge';
1314
- const MaskIcon = 'MaskIcon';
1315
- const SourceControlBadge = 'SourceControlBadge';
1316
-
1317
- const Directory = 3;
1318
- const DirectoryExpanded = 4;
1319
- const File = 7;
1320
-
1321
- const Button$2 = 1;
1322
- const Div = 4;
1323
- const Span = 8;
1324
- const Text = 12;
1325
- const Img = 17;
1326
- const TextArea = 62;
1327
- const Reference = 100;
1328
-
1329
- const Button$1 = 'event.button';
1330
- const ClientX = 'event.clientX';
1331
- const ClientY = 'event.clientY';
1332
- const DeltaMode = 'event.deltaMode';
1333
- const DeltaY = 'event.deltaY';
1334
- const TargetName = 'event.target.name';
1335
- const TargetValue = 'event.target.value';
1336
-
1337
- const Enter = 3;
1338
-
1339
- const User = 1;
1340
- const Script = 2;
1341
-
1342
- const CtrlCmd = 1 << 11 >>> 0;
1343
-
1344
- const SourceControl$1 = 22;
1345
-
1346
- const None = 0;
1347
-
1348
- const Web = 1;
1349
- const Electron = 2;
1350
- const Remote = 3;
1351
-
1352
- const SetCss = 'Viewlet.setCss';
1353
- const SetDom2 = 'Viewlet.setDom2';
1354
- const SetFocusContext = 'Viewlet.setFocusContext';
1355
- const SetValueByName = 'Viewlet.setValueByName';
1356
-
1357
- const List$1 = 1;
1358
- const Tree = 2;
1359
-
1360
- const FocusSourceControlInput = 24;
1361
-
1362
1670
  const getActualDecorationIcon = (iconDefinitions, icon) => {
1363
1671
  if (typeof icon === 'number') {
1364
1672
  const value = iconDefinitions[icon];
@@ -1531,7 +1839,7 @@ const executeProvider = async ({
1531
1839
  return result;
1532
1840
  };
1533
1841
 
1534
- const CommandExecute = 'ExtensionHostCommand.executeCommand';
1842
+ const CommandExecute = 'Extensions.executeCommand';
1535
1843
  const SourceControlAcceptInput = 'ExtensionHostSourceControl.acceptInput';
1536
1844
  const SourceControlGenerateCommitMessage = 'ExtensionHostSourceControl.generateCommitMessage';
1537
1845
  const SourceControlGetBadgeCount = 'ExtensionHostSourceControl.getBadgeCount';
@@ -1744,8 +2052,9 @@ const getIconDefinitions = async (providerIds, assetDir, platform) => {
1744
2052
  return [];
1745
2053
  }
1746
2054
  const icons = extension['source-control-icons'].filter(icon => typeof icon === 'string');
2055
+ const baseUri = extension.uri.endsWith('/') ? extension.uri : `${extension.uri}/`;
1747
2056
  return icons.map(icon => {
1748
- const uri = `${extension.uri}/${icon}`;
2057
+ const uri = new URL(icon, baseUri).href;
1749
2058
  if (platform === Electron || platform === Remote) {
1750
2059
  const protocol = getProtocol(uri);
1751
2060
  const path = getPath(protocol, uri);
@@ -1820,15 +2129,15 @@ const getNumberOfVisibleItems = (listHeight, itemHeight) => {
1820
2129
  };
1821
2130
 
1822
2131
  const emptyObject = {};
1823
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1824
2132
  const i18nString = (key, placeholders = emptyObject) => {
1825
2133
  if (placeholders === emptyObject) {
1826
2134
  return key;
1827
2135
  }
1828
- const replacer = (match, rest) => {
1829
- return placeholders[rest];
1830
- };
1831
- return key.replaceAll(RE_PLACEHOLDER, replacer);
2136
+ let result = key;
2137
+ for (const [placeholder, replacement] of Object.entries(placeholders)) {
2138
+ result = result.split(`{${placeholder}}`).join(String(replacement));
2139
+ }
2140
+ return result;
1832
2141
  };
1833
2142
 
1834
2143
  const OpenChanges = 'Open Changes';
@@ -2342,6 +2651,8 @@ const text = data => {
2342
2651
  };
2343
2652
  };
2344
2653
 
2654
+ new Set(Object.values(VirtualDomElements));
2655
+
2345
2656
  const SetText = 1;
2346
2657
  const Replace = 2;
2347
2658
  const SetAttribute = 3;
@@ -2413,21 +2724,18 @@ const getChildrenWithCount = (nodes, startIndex, childCount) => {
2413
2724
  };
2414
2725
 
2415
2726
  const compareNodes = (oldNode, newNode) => {
2416
- const patches = [];
2417
2727
  // Check if node type changed - return null to signal incompatible nodes
2418
2728
  // (caller should handle this with a Replace operation)
2419
2729
  if (oldNode.type !== newNode.type) {
2420
2730
  return null;
2421
2731
  }
2732
+ const patches = [];
2422
2733
  // Handle reference nodes - special handling for uid changes
2423
- if (oldNode.type === Reference) {
2424
- if (oldNode.uid !== newNode.uid) {
2425
- patches.push({
2426
- type: SetReferenceNodeUid,
2427
- uid: newNode.uid
2428
- });
2429
- }
2430
- return patches;
2734
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
2735
+ patches.push({
2736
+ type: SetReferenceNodeUid,
2737
+ uid: newNode.uid
2738
+ });
2431
2739
  }
2432
2740
  // Handle text nodes
2433
2741
  if (oldNode.type === Text && newNode.type === Text) {
@@ -2440,8 +2748,8 @@ const compareNodes = (oldNode, newNode) => {
2440
2748
  return patches;
2441
2749
  }
2442
2750
  // Compare attributes
2443
- const oldKeys = getKeys(oldNode);
2444
- const newKeys = getKeys(newNode);
2751
+ const oldKeys = getKeys(oldNode).filter(key => oldNode.type !== Reference || key !== 'uid');
2752
+ const newKeys = getKeys(newNode).filter(key => newNode.type !== Reference || key !== 'uid');
2445
2753
  // Check for attribute changes
2446
2754
  for (const key of newKeys) {
2447
2755
  if (oldNode[key] !== newNode[key]) {
@@ -2454,7 +2762,7 @@ const compareNodes = (oldNode, newNode) => {
2454
2762
  }
2455
2763
  // Check for removed attributes
2456
2764
  for (const key of oldKeys) {
2457
- if (!(key in newNode)) {
2765
+ if (!Object.hasOwn(newNode, key)) {
2458
2766
  patches.push({
2459
2767
  type: RemoveAttribute,
2460
2768
  key
@@ -2465,18 +2773,90 @@ const compareNodes = (oldNode, newNode) => {
2465
2773
  };
2466
2774
 
2467
2775
  const treeToArray = node => {
2468
- const result = [node.node];
2469
- for (const child of node.children) {
2470
- result.push(...treeToArray(child));
2776
+ const result = [];
2777
+ const stack = [node];
2778
+ while (stack.length > 0) {
2779
+ const current = stack.pop();
2780
+ result.push(current.node);
2781
+ for (let i = current.children.length - 1; i >= 0; i--) {
2782
+ stack.push(current.children[i]);
2783
+ }
2471
2784
  }
2472
2785
  return result;
2473
2786
  };
2474
2787
 
2788
+ const navigateToChild = (patches, currentChildIndex, index) => {
2789
+ if (currentChildIndex === -1) {
2790
+ patches.push({
2791
+ type: NavigateChild,
2792
+ index
2793
+ });
2794
+ return index;
2795
+ }
2796
+ if (currentChildIndex !== index) {
2797
+ patches.push({
2798
+ type: NavigateSibling,
2799
+ index
2800
+ });
2801
+ }
2802
+ return index;
2803
+ };
2804
+ const navigateToParent = (patches, currentChildIndex) => {
2805
+ if (currentChildIndex >= 0) {
2806
+ patches.push({
2807
+ type: NavigateParent
2808
+ });
2809
+ }
2810
+ return -1;
2811
+ };
2812
+ const addTree = (newNode, patches) => {
2813
+ patches.push({
2814
+ type: Add,
2815
+ nodes: treeToArray(newNode)
2816
+ });
2817
+ };
2818
+ const replaceTree = (newNode, patches) => {
2819
+ patches.push({
2820
+ type: Replace,
2821
+ nodes: treeToArray(newNode)
2822
+ });
2823
+ };
2824
+ const diffExistingChild = (oldNode, newNode, patches, currentChildIndex, index) => {
2825
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
2826
+ if (nodePatches === null) {
2827
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
2828
+ replaceTree(newNode, patches);
2829
+ return nextChildIndex;
2830
+ }
2831
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
2832
+ if (nodePatches.length === 0 && !hasChildrenToCompare) {
2833
+ return currentChildIndex;
2834
+ }
2835
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
2836
+ if (nodePatches.length > 0) {
2837
+ patches.push(...nodePatches);
2838
+ }
2839
+ if (hasChildrenToCompare) {
2840
+ diffChildren(oldNode.children, newNode.children, patches);
2841
+ }
2842
+ return nextChildIndex;
2843
+ };
2844
+ const diffRootNode = (oldNode, newNode, patches) => {
2845
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
2846
+ if (nodePatches === null) {
2847
+ replaceTree(newNode, patches);
2848
+ return;
2849
+ }
2850
+ if (nodePatches.length > 0) {
2851
+ patches.push(...nodePatches);
2852
+ }
2853
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
2854
+ diffChildren(oldNode.children, newNode.children, patches);
2855
+ }
2856
+ };
2475
2857
  const diffChildren = (oldChildren, newChildren, patches) => {
2476
2858
  const maxLength = Math.max(oldChildren.length, newChildren.length);
2477
- // Track where we are: -1 means at parent, >= 0 means at child index
2478
2859
  let currentChildIndex = -1;
2479
- // Collect indices of children to remove (we'll add these patches at the end in reverse order)
2480
2860
  const indicesToRemove = [];
2481
2861
  for (let i = 0; i < maxLength; i++) {
2482
2862
  const oldNode = oldChildren[i];
@@ -2485,88 +2865,17 @@ const diffChildren = (oldChildren, newChildren, patches) => {
2485
2865
  continue;
2486
2866
  }
2487
2867
  if (!oldNode) {
2488
- // Add new node - we should be at the parent
2489
- if (currentChildIndex >= 0) {
2490
- // Navigate back to parent
2491
- patches.push({
2492
- type: NavigateParent
2493
- });
2494
- currentChildIndex = -1;
2495
- }
2496
- // Flatten the entire subtree so renderInternal can handle it
2497
- const flatNodes = treeToArray(newNode);
2498
- patches.push({
2499
- type: Add,
2500
- nodes: flatNodes
2501
- });
2502
- } else if (newNode) {
2503
- // Compare nodes to see if we need any patches
2504
- const nodePatches = compareNodes(oldNode.node, newNode.node);
2505
- // If nodePatches is null, the node types are incompatible - need to replace
2506
- if (nodePatches === null) {
2507
- // Navigate to this child
2508
- if (currentChildIndex === -1) {
2509
- patches.push({
2510
- type: NavigateChild,
2511
- index: i
2512
- });
2513
- currentChildIndex = i;
2514
- } else if (currentChildIndex !== i) {
2515
- patches.push({
2516
- type: NavigateSibling,
2517
- index: i
2518
- });
2519
- currentChildIndex = i;
2520
- }
2521
- // Replace the entire subtree
2522
- const flatNodes = treeToArray(newNode);
2523
- patches.push({
2524
- type: Replace,
2525
- nodes: flatNodes
2526
- });
2527
- // After replace, we're at the new element (same position)
2528
- continue;
2529
- }
2530
- // Check if we need to recurse into children
2531
- const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
2532
- // Only navigate to this element if we need to do something
2533
- if (nodePatches.length > 0 || hasChildrenToCompare) {
2534
- // Navigate to this child if not already there
2535
- if (currentChildIndex === -1) {
2536
- patches.push({
2537
- type: NavigateChild,
2538
- index: i
2539
- });
2540
- currentChildIndex = i;
2541
- } else if (currentChildIndex !== i) {
2542
- patches.push({
2543
- type: NavigateSibling,
2544
- index: i
2545
- });
2546
- currentChildIndex = i;
2547
- }
2548
- // Apply node patches (these apply to the current element, not children)
2549
- if (nodePatches.length > 0) {
2550
- patches.push(...nodePatches);
2551
- }
2552
- // Compare children recursively
2553
- if (hasChildrenToCompare) {
2554
- diffChildren(oldNode.children, newNode.children, patches);
2555
- }
2556
- }
2557
- } else {
2558
- // Remove old node - collect the index for later removal
2868
+ currentChildIndex = navigateToParent(patches, currentChildIndex);
2869
+ addTree(newNode, patches);
2870
+ continue;
2871
+ }
2872
+ if (!newNode) {
2559
2873
  indicesToRemove.push(i);
2874
+ continue;
2560
2875
  }
2876
+ currentChildIndex = diffExistingChild(oldNode, newNode, patches, currentChildIndex, i);
2561
2877
  }
2562
- // Navigate back to parent if we ended at a child
2563
- if (currentChildIndex >= 0) {
2564
- patches.push({
2565
- type: NavigateParent
2566
- });
2567
- }
2568
- // Add remove patches in reverse order (highest index first)
2569
- // This ensures indices remain valid as we remove
2878
+ navigateToParent(patches, currentChildIndex);
2570
2879
  for (let j = indicesToRemove.length - 1; j >= 0; j--) {
2571
2880
  patches.push({
2572
2881
  type: RemoveChild,
@@ -2575,47 +2884,22 @@ const diffChildren = (oldChildren, newChildren, patches) => {
2575
2884
  }
2576
2885
  };
2577
2886
  const diffTrees = (oldTree, newTree, patches, path) => {
2578
- // At the root level (path.length === 0), we're already AT the element
2579
- // So we compare the root node directly, then compare its children
2580
2887
  if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
2581
- const oldNode = oldTree[0];
2582
- const newNode = newTree[0];
2583
- // Compare root nodes
2584
- const nodePatches = compareNodes(oldNode.node, newNode.node);
2585
- // If nodePatches is null, the root node types are incompatible - need to replace
2586
- if (nodePatches === null) {
2587
- const flatNodes = treeToArray(newNode);
2588
- patches.push({
2589
- type: Replace,
2590
- nodes: flatNodes
2591
- });
2592
- return;
2593
- }
2594
- if (nodePatches.length > 0) {
2595
- patches.push(...nodePatches);
2596
- }
2597
- // Compare children
2598
- if (oldNode.children.length > 0 || newNode.children.length > 0) {
2599
- diffChildren(oldNode.children, newNode.children, patches);
2600
- }
2601
- } else {
2602
- // Non-root level or multiple root elements - use the regular comparison
2603
- diffChildren(oldTree, newTree, patches);
2888
+ diffRootNode(oldTree[0], newTree[0], patches);
2889
+ return;
2604
2890
  }
2891
+ diffChildren(oldTree, newTree, patches);
2605
2892
  };
2606
2893
 
2607
2894
  const removeTrailingNavigationPatches = patches => {
2608
- // Find the last non-navigation patch
2609
- let lastNonNavigationIndex = -1;
2610
- for (let i = patches.length - 1; i >= 0; i--) {
2611
- const patch = patches[i];
2895
+ while (patches.length > 0) {
2896
+ const patch = patches.at(-1);
2612
2897
  if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
2613
- lastNonNavigationIndex = i;
2614
2898
  break;
2615
2899
  }
2900
+ patches.pop();
2616
2901
  }
2617
- // Return patches up to and including the last non-navigation patch
2618
- return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
2902
+ return patches;
2619
2903
  };
2620
2904
 
2621
2905
  const diffTree = (oldNodes, newNodes) => {
@@ -3251,22 +3535,6 @@ const handleWorkspaceRefresh = async state => {
3251
3535
  });
3252
3536
  };
3253
3537
 
3254
- const sendMessagePortToExtensionHostWorker = async port => {
3255
- await sendMessagePortToExtensionHostWorker$1(port, SourceControlWorker);
3256
- };
3257
-
3258
- const createExtensionHostRpc = async () => {
3259
- try {
3260
- const rpc = await create$3({
3261
- commandMap: {},
3262
- send: sendMessagePortToExtensionHostWorker
3263
- });
3264
- return rpc;
3265
- } catch (error) {
3266
- throw new VError(error, `Failed to create extension host rpc`);
3267
- }
3268
- };
3269
-
3270
3538
  const sendMessagePortToTextMeasurementWorker = async port => {
3271
3539
  await sendMessagePortToTextMeasurementWorker$1(port);
3272
3540
  };
@@ -3299,15 +3567,15 @@ const initializeExtensionManagementWorker = async () => {
3299
3567
  try {
3300
3568
  const rpc = await createExtensionManagementWorkerRpc();
3301
3569
  set$5(rpc);
3570
+ set$6(rpc);
3302
3571
  } catch {
3303
3572
  // ignore
3304
3573
  }
3305
3574
  };
3306
3575
 
3307
3576
  const initialize = async () => {
3308
- const [extensionHostRpc, textRpc] = await Promise.all([createExtensionHostRpc(), createTextMeasurementWorkerRpc(), initializeExtensionManagementWorker()]);
3309
- set$6(extensionHostRpc);
3310
- set$2(textRpc);
3577
+ const [textRpc] = await Promise.all([createTextMeasurementWorkerRpc(), initializeExtensionManagementWorker()]);
3578
+ set$3(textRpc);
3311
3579
  };
3312
3580
 
3313
3581
  const getIndentRule = indent => {
@@ -3344,11 +3612,18 @@ const renderCss = (oldState, newState) => {
3344
3612
  const listHeight = Math.max(height - headerHeight, 0);
3345
3613
  const scrollBarY = scrollBarHeight > 0 ? getScrollBarY(deltaY, finalDeltaY, listHeight, scrollBarHeight) : 0;
3346
3614
  const itemOffset = -(deltaY % itemHeight);
3347
- const indentCss = indentRules ? `\n${indentRules}\n` : '';
3615
+ const indentCss = indentRules ? `${indentRules}\n` : '';
3348
3616
  const css = `:root {
3349
3617
  --SourceControlInputHeight: ${inputBoxHeight}px;
3350
3618
  }
3351
3619
 
3620
+ .SourceControl .SplitButtonContent > .MaskIcon {
3621
+ width: 16px;
3622
+ height: 16px;
3623
+ margin-right: 4px;
3624
+ flex-shrink: 0;
3625
+ }
3626
+
3352
3627
  .SourceControl .ScrollBarThumb {
3353
3628
  height: ${scrollBarHeight}px;
3354
3629
  translate: 0 ${Math.round(scrollBarY)}px;
@@ -3357,7 +3632,11 @@ const renderCss = (oldState, newState) => {
3357
3632
  .SourceControlItems > .TreeItem:first-child {
3358
3633
  margin-top: ${itemOffset}px;
3359
3634
  }
3360
- ${indentCss}`;
3635
+
3636
+ ${indentCss}.IndentRight-12 {
3637
+ padding-right: 12px;
3638
+ }
3639
+ `;
3361
3640
  return [SetCss, id, css];
3362
3641
  };
3363
3642
 
@@ -3381,6 +3660,7 @@ const InputBox = 'InputBox';
3381
3660
  const Label = 'Label';
3382
3661
  const LabelDetail = 'LabelDetail';
3383
3662
  const List = 'List';
3663
+ const ListItems = 'ListItems';
3384
3664
  const Message = 'Message';
3385
3665
  const Progress = 'Progress';
3386
3666
  const ProgressContainer = 'ProgressContainer';
@@ -3399,6 +3679,7 @@ const SplitButtonDisabled = 'SplitButtonDisabled';
3399
3679
  const StrikeThrough = 'StrikeThrough';
3400
3680
  const TreeItem = 'TreeItem';
3401
3681
  const Viewlet = 'Viewlet';
3682
+ const ViewSourceControlInput = 'ViewSourceControlInput';
3402
3683
 
3403
3684
  const HandleClickAt = 1;
3404
3685
  const HandleContextMenu = 2;
@@ -3469,8 +3750,13 @@ const messageNode$1 = {
3469
3750
  className: Message,
3470
3751
  type: Div
3471
3752
  };
3753
+ const inputWrapperNode = {
3754
+ childCount: 1,
3755
+ className: ViewSourceControlInput,
3756
+ type: Div
3757
+ };
3472
3758
  const getSourceControlInputDom = (inputPlaceholder, inputMessage) => {
3473
- const dom = [{
3759
+ const dom = [inputWrapperNode, {
3474
3760
  ariaLabel: sourceControlInput(),
3475
3761
  autocapitalize: 'off',
3476
3762
  autocorrect: 'off',
@@ -3564,13 +3850,9 @@ const getLabelClassName = decorationStrikeThrough => {
3564
3850
  };
3565
3851
 
3566
3852
  const getTreeItemClassName = indent => {
3567
- let className = TreeItem;
3568
- className = mergeClassNames(className, `Indent-${indent}`);
3569
- return className;
3853
+ return mergeClassNames(TreeItem, `Indent-${indent}`, 'IndentRight-12');
3570
3854
  };
3571
3855
 
3572
- const PaddingRight = '12px';
3573
-
3574
3856
  const createItemDirectory = item => {
3575
3857
  const {
3576
3858
  badgeCount,
@@ -3593,7 +3875,6 @@ const createItemDirectory = item => {
3593
3875
  ariaSetSize: setSize,
3594
3876
  childCount: 3 + (hasButtons ? 1 : 0),
3595
3877
  className: treeItemClassName,
3596
- paddingRight: PaddingRight,
3597
3878
  role: TreeItem$1,
3598
3879
  type: Div
3599
3880
  }, {
@@ -3658,7 +3939,6 @@ const createItemOther = item => {
3658
3939
  ariaSetSize: setSize,
3659
3940
  childCount: 3 + (hasButtons ? 1 : 0),
3660
3941
  className: treeItemClassName,
3661
- paddingRight: '12px',
3662
3942
  role: TreeItem$1,
3663
3943
  title: file,
3664
3944
  type: Div
@@ -3702,7 +3982,7 @@ const getSourceControlListVirtualDom = (items, scrollBarHeight, scrollBarActive)
3702
3982
  type: Div
3703
3983
  }, {
3704
3984
  childCount: items.length,
3705
- className: SourceControlItems,
3985
+ className: mergeClassNames(ListItems, SourceControlItems),
3706
3986
  onClick: HandleClickAt,
3707
3987
  onPointerOut: HandleMouseOutAt,
3708
3988
  onPointerOver: HandleMouseOverAt,
@@ -3969,14 +4249,19 @@ const renderEventListeners = () => {
3969
4249
  }];
3970
4250
  };
3971
4251
 
3972
- const revealInExplorer = async (state, uri) => {
4252
+ const timerGlobal = globalThis;
4253
+ const revealInExplorerActual = async uri => {
3973
4254
  await invoke$1('SideBar.show', 'Explorer');
3974
4255
  const states = await invoke$1('Viewlet.getAllStates');
3975
4256
  const viewlets = Object.values(states);
3976
4257
  const sideBar = viewlets.find(viewlet => viewlet.currentViewletId === 'Explorer');
3977
4258
  const explorerUid = Math.max(...viewlets.filter(viewlet => viewlet.parentUid === sideBar.uid).map(viewlet => viewlet.uid));
3978
4259
  await invoke$1('Viewlet.executeViewletCommand', explorerUid, 'reveal', uri);
3979
- await invoke$1('Viewlet.executeViewletCommand', explorerUid, 'refresh');
4260
+ };
4261
+ const revealInExplorer = (state, uri) => {
4262
+ timerGlobal.setTimeout(() => {
4263
+ void revealInExplorerActual(uri);
4264
+ }, 0);
3980
4265
  return state;
3981
4266
  };
3982
4267
 
@@ -4081,7 +4366,7 @@ const listen = async () => {
4081
4366
  const rpc = await create$2({
4082
4367
  commandMap: commandMap
4083
4368
  });
4084
- set$3(rpc);
4369
+ set$2(rpc);
4085
4370
  };
4086
4371
 
4087
4372
  const main = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/source-control-worker",
3
- "version": "3.14.0",
3
+ "version": "3.15.0",
4
4
  "description": "Source Control Worker",
5
5
  "keywords": [
6
6
  "Lvce Editor"