@lvce-editor/source-control-worker 3.14.1 → 3.16.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';
@@ -1821,15 +2129,15 @@ const getNumberOfVisibleItems = (listHeight, itemHeight) => {
1821
2129
  };
1822
2130
 
1823
2131
  const emptyObject = {};
1824
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1825
2132
  const i18nString = (key, placeholders = emptyObject) => {
1826
2133
  if (placeholders === emptyObject) {
1827
2134
  return key;
1828
2135
  }
1829
- const replacer = (match, rest) => {
1830
- return placeholders[rest];
1831
- };
1832
- 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;
1833
2141
  };
1834
2142
 
1835
2143
  const OpenChanges = 'Open Changes';
@@ -2343,6 +2651,8 @@ const text = data => {
2343
2651
  };
2344
2652
  };
2345
2653
 
2654
+ new Set(Object.values(VirtualDomElements));
2655
+
2346
2656
  const SetText = 1;
2347
2657
  const Replace = 2;
2348
2658
  const SetAttribute = 3;
@@ -2414,21 +2724,18 @@ const getChildrenWithCount = (nodes, startIndex, childCount) => {
2414
2724
  };
2415
2725
 
2416
2726
  const compareNodes = (oldNode, newNode) => {
2417
- const patches = [];
2418
2727
  // Check if node type changed - return null to signal incompatible nodes
2419
2728
  // (caller should handle this with a Replace operation)
2420
2729
  if (oldNode.type !== newNode.type) {
2421
2730
  return null;
2422
2731
  }
2732
+ const patches = [];
2423
2733
  // Handle reference nodes - special handling for uid changes
2424
- if (oldNode.type === Reference) {
2425
- if (oldNode.uid !== newNode.uid) {
2426
- patches.push({
2427
- type: SetReferenceNodeUid,
2428
- uid: newNode.uid
2429
- });
2430
- }
2431
- return patches;
2734
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
2735
+ patches.push({
2736
+ type: SetReferenceNodeUid,
2737
+ uid: newNode.uid
2738
+ });
2432
2739
  }
2433
2740
  // Handle text nodes
2434
2741
  if (oldNode.type === Text && newNode.type === Text) {
@@ -2441,8 +2748,8 @@ const compareNodes = (oldNode, newNode) => {
2441
2748
  return patches;
2442
2749
  }
2443
2750
  // Compare attributes
2444
- const oldKeys = getKeys(oldNode);
2445
- 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');
2446
2753
  // Check for attribute changes
2447
2754
  for (const key of newKeys) {
2448
2755
  if (oldNode[key] !== newNode[key]) {
@@ -2455,7 +2762,7 @@ const compareNodes = (oldNode, newNode) => {
2455
2762
  }
2456
2763
  // Check for removed attributes
2457
2764
  for (const key of oldKeys) {
2458
- if (!(key in newNode)) {
2765
+ if (!Object.hasOwn(newNode, key)) {
2459
2766
  patches.push({
2460
2767
  type: RemoveAttribute,
2461
2768
  key
@@ -2466,18 +2773,90 @@ const compareNodes = (oldNode, newNode) => {
2466
2773
  };
2467
2774
 
2468
2775
  const treeToArray = node => {
2469
- const result = [node.node];
2470
- for (const child of node.children) {
2471
- 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
+ }
2472
2784
  }
2473
2785
  return result;
2474
2786
  };
2475
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
+ };
2476
2857
  const diffChildren = (oldChildren, newChildren, patches) => {
2477
2858
  const maxLength = Math.max(oldChildren.length, newChildren.length);
2478
- // Track where we are: -1 means at parent, >= 0 means at child index
2479
2859
  let currentChildIndex = -1;
2480
- // Collect indices of children to remove (we'll add these patches at the end in reverse order)
2481
2860
  const indicesToRemove = [];
2482
2861
  for (let i = 0; i < maxLength; i++) {
2483
2862
  const oldNode = oldChildren[i];
@@ -2486,88 +2865,17 @@ const diffChildren = (oldChildren, newChildren, patches) => {
2486
2865
  continue;
2487
2866
  }
2488
2867
  if (!oldNode) {
2489
- // Add new node - we should be at the parent
2490
- if (currentChildIndex >= 0) {
2491
- // Navigate back to parent
2492
- patches.push({
2493
- type: NavigateParent
2494
- });
2495
- currentChildIndex = -1;
2496
- }
2497
- // Flatten the entire subtree so renderInternal can handle it
2498
- const flatNodes = treeToArray(newNode);
2499
- patches.push({
2500
- type: Add,
2501
- nodes: flatNodes
2502
- });
2503
- } else if (newNode) {
2504
- // Compare nodes to see if we need any patches
2505
- const nodePatches = compareNodes(oldNode.node, newNode.node);
2506
- // If nodePatches is null, the node types are incompatible - need to replace
2507
- if (nodePatches === null) {
2508
- // Navigate to this child
2509
- if (currentChildIndex === -1) {
2510
- patches.push({
2511
- type: NavigateChild,
2512
- index: i
2513
- });
2514
- currentChildIndex = i;
2515
- } else if (currentChildIndex !== i) {
2516
- patches.push({
2517
- type: NavigateSibling,
2518
- index: i
2519
- });
2520
- currentChildIndex = i;
2521
- }
2522
- // Replace the entire subtree
2523
- const flatNodes = treeToArray(newNode);
2524
- patches.push({
2525
- type: Replace,
2526
- nodes: flatNodes
2527
- });
2528
- // After replace, we're at the new element (same position)
2529
- continue;
2530
- }
2531
- // Check if we need to recurse into children
2532
- const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
2533
- // Only navigate to this element if we need to do something
2534
- if (nodePatches.length > 0 || hasChildrenToCompare) {
2535
- // Navigate to this child if not already there
2536
- if (currentChildIndex === -1) {
2537
- patches.push({
2538
- type: NavigateChild,
2539
- index: i
2540
- });
2541
- currentChildIndex = i;
2542
- } else if (currentChildIndex !== i) {
2543
- patches.push({
2544
- type: NavigateSibling,
2545
- index: i
2546
- });
2547
- currentChildIndex = i;
2548
- }
2549
- // Apply node patches (these apply to the current element, not children)
2550
- if (nodePatches.length > 0) {
2551
- patches.push(...nodePatches);
2552
- }
2553
- // Compare children recursively
2554
- if (hasChildrenToCompare) {
2555
- diffChildren(oldNode.children, newNode.children, patches);
2556
- }
2557
- }
2558
- } else {
2559
- // Remove old node - collect the index for later removal
2868
+ currentChildIndex = navigateToParent(patches, currentChildIndex);
2869
+ addTree(newNode, patches);
2870
+ continue;
2871
+ }
2872
+ if (!newNode) {
2560
2873
  indicesToRemove.push(i);
2874
+ continue;
2561
2875
  }
2876
+ currentChildIndex = diffExistingChild(oldNode, newNode, patches, currentChildIndex, i);
2562
2877
  }
2563
- // Navigate back to parent if we ended at a child
2564
- if (currentChildIndex >= 0) {
2565
- patches.push({
2566
- type: NavigateParent
2567
- });
2568
- }
2569
- // Add remove patches in reverse order (highest index first)
2570
- // This ensures indices remain valid as we remove
2878
+ navigateToParent(patches, currentChildIndex);
2571
2879
  for (let j = indicesToRemove.length - 1; j >= 0; j--) {
2572
2880
  patches.push({
2573
2881
  type: RemoveChild,
@@ -2576,47 +2884,22 @@ const diffChildren = (oldChildren, newChildren, patches) => {
2576
2884
  }
2577
2885
  };
2578
2886
  const diffTrees = (oldTree, newTree, patches, path) => {
2579
- // At the root level (path.length === 0), we're already AT the element
2580
- // So we compare the root node directly, then compare its children
2581
2887
  if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
2582
- const oldNode = oldTree[0];
2583
- const newNode = newTree[0];
2584
- // Compare root nodes
2585
- const nodePatches = compareNodes(oldNode.node, newNode.node);
2586
- // If nodePatches is null, the root node types are incompatible - need to replace
2587
- if (nodePatches === null) {
2588
- const flatNodes = treeToArray(newNode);
2589
- patches.push({
2590
- type: Replace,
2591
- nodes: flatNodes
2592
- });
2593
- return;
2594
- }
2595
- if (nodePatches.length > 0) {
2596
- patches.push(...nodePatches);
2597
- }
2598
- // Compare children
2599
- if (oldNode.children.length > 0 || newNode.children.length > 0) {
2600
- diffChildren(oldNode.children, newNode.children, patches);
2601
- }
2602
- } else {
2603
- // Non-root level or multiple root elements - use the regular comparison
2604
- diffChildren(oldTree, newTree, patches);
2888
+ diffRootNode(oldTree[0], newTree[0], patches);
2889
+ return;
2605
2890
  }
2891
+ diffChildren(oldTree, newTree, patches);
2606
2892
  };
2607
2893
 
2608
2894
  const removeTrailingNavigationPatches = patches => {
2609
- // Find the last non-navigation patch
2610
- let lastNonNavigationIndex = -1;
2611
- for (let i = patches.length - 1; i >= 0; i--) {
2612
- const patch = patches[i];
2895
+ while (patches.length > 0) {
2896
+ const patch = patches.at(-1);
2613
2897
  if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
2614
- lastNonNavigationIndex = i;
2615
2898
  break;
2616
2899
  }
2900
+ patches.pop();
2617
2901
  }
2618
- // Return patches up to and including the last non-navigation patch
2619
- return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
2902
+ return patches;
2620
2903
  };
2621
2904
 
2622
2905
  const diffTree = (oldNodes, newNodes) => {
@@ -3103,7 +3386,7 @@ const set = rpc => {
3103
3386
  state.connected = true;
3104
3387
  };
3105
3388
 
3106
- const handleRendererProcessMessagePort = async (port, viewletCommandMap) => {
3389
+ const handleRendererProcessMessagePort = async (port, viewletCommandMap, setAsRendererProcess = true) => {
3107
3390
  const executeViewletCommand = async (uid, command, ...args) => {
3108
3391
  const fn = viewletCommandMap[`SourceControl.${command}`];
3109
3392
  if (typeof fn !== 'function') {
@@ -3118,7 +3401,9 @@ const handleRendererProcessMessagePort = async (port, viewletCommandMap) => {
3118
3401
  },
3119
3402
  messagePort: port
3120
3403
  });
3121
- set(rpc);
3404
+ if (setAsRendererProcess) {
3405
+ set(rpc);
3406
+ }
3122
3407
  };
3123
3408
 
3124
3409
  const handleScrollBarCaptureLost = state => {
@@ -3252,22 +3537,6 @@ const handleWorkspaceRefresh = async state => {
3252
3537
  });
3253
3538
  };
3254
3539
 
3255
- const sendMessagePortToExtensionHostWorker = async port => {
3256
- await sendMessagePortToExtensionHostWorker$1(port, SourceControlWorker);
3257
- };
3258
-
3259
- const createExtensionHostRpc = async () => {
3260
- try {
3261
- const rpc = await create$3({
3262
- commandMap: {},
3263
- send: sendMessagePortToExtensionHostWorker
3264
- });
3265
- return rpc;
3266
- } catch (error) {
3267
- throw new VError(error, `Failed to create extension host rpc`);
3268
- }
3269
- };
3270
-
3271
3540
  const sendMessagePortToTextMeasurementWorker = async port => {
3272
3541
  await sendMessagePortToTextMeasurementWorker$1(port);
3273
3542
  };
@@ -3300,15 +3569,15 @@ const initializeExtensionManagementWorker = async () => {
3300
3569
  try {
3301
3570
  const rpc = await createExtensionManagementWorkerRpc();
3302
3571
  set$5(rpc);
3572
+ set$6(rpc);
3303
3573
  } catch {
3304
3574
  // ignore
3305
3575
  }
3306
3576
  };
3307
3577
 
3308
3578
  const initialize = async () => {
3309
- const [extensionHostRpc, textRpc] = await Promise.all([createExtensionHostRpc(), createTextMeasurementWorkerRpc(), initializeExtensionManagementWorker()]);
3310
- set$6(extensionHostRpc);
3311
- set$2(textRpc);
3579
+ const [textRpc] = await Promise.all([createTextMeasurementWorkerRpc(), initializeExtensionManagementWorker()]);
3580
+ set$3(textRpc);
3312
3581
  };
3313
3582
 
3314
3583
  const getIndentRule = indent => {
@@ -3982,14 +4251,19 @@ const renderEventListeners = () => {
3982
4251
  }];
3983
4252
  };
3984
4253
 
3985
- const revealInExplorer = async (state, uri) => {
4254
+ const timerGlobal = globalThis;
4255
+ const revealInExplorerActual = async uri => {
3986
4256
  await invoke$1('SideBar.show', 'Explorer');
3987
4257
  const states = await invoke$1('Viewlet.getAllStates');
3988
4258
  const viewlets = Object.values(states);
3989
4259
  const sideBar = viewlets.find(viewlet => viewlet.currentViewletId === 'Explorer');
3990
4260
  const explorerUid = Math.max(...viewlets.filter(viewlet => viewlet.parentUid === sideBar.uid).map(viewlet => viewlet.uid));
3991
4261
  await invoke$1('Viewlet.executeViewletCommand', explorerUid, 'reveal', uri);
3992
- await invoke$1('Viewlet.executeViewletCommand', explorerUid, 'refresh');
4262
+ };
4263
+ const revealInExplorer = (state, uri) => {
4264
+ timerGlobal.setTimeout(() => {
4265
+ void revealInExplorerActual(uri);
4266
+ }, 0);
3993
4267
  return state;
3994
4268
  };
3995
4269
 
@@ -4037,7 +4311,7 @@ const viewAsList = state => {
4037
4311
  };
4038
4312
  };
4039
4313
 
4040
- const handleDirectMessagePort = port => handleRendererProcessMessagePort(port, commandMap);
4314
+ const handleDirectMessagePort = (port, setAsRendererProcess = true) => handleRendererProcessMessagePort(port, commandMap, setAsRendererProcess);
4041
4315
  const commandMap = {
4042
4316
  'Initialize.initialize': initialize,
4043
4317
  'SourceControl.acceptInput': wrapCommand(acceptInput),
@@ -4094,7 +4368,7 @@ const listen = async () => {
4094
4368
  const rpc = await create$2({
4095
4369
  commandMap: commandMap
4096
4370
  });
4097
- set$3(rpc);
4371
+ set$2(rpc);
4098
4372
  };
4099
4373
 
4100
4374
  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.1",
3
+ "version": "3.16.0",
4
4
  "description": "Source Control Worker",
5
5
  "keywords": [
6
6
  "Lvce Editor"