@lvce-editor/quick-pick-worker 4.18.0 → 4.19.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.
@@ -1182,13 +1182,175 @@ const create$4 = rpcId => {
1182
1182
  };
1183
1183
  };
1184
1184
 
1185
+ const Audio = 0;
1186
+ const Button = 1;
1187
+ const Col = 2;
1188
+ const ColGroup = 3;
1185
1189
  const Div = 4;
1190
+ const H1 = 5;
1186
1191
  const Input = 6;
1192
+ const Kbd = 7;
1187
1193
  const Span = 8;
1194
+ const Table = 9;
1195
+ const TBody = 10;
1196
+ const Td = 11;
1188
1197
  const Text = 12;
1198
+ const Th = 13;
1199
+ const THead = 14;
1200
+ const Tr = 15;
1201
+ const I = 16;
1189
1202
  const Img = 17;
1203
+ const Root = 0;
1204
+ const Ins = 20;
1205
+ const Del = 21;
1206
+ const H2 = 22;
1207
+ const H3 = 23;
1208
+ const H4 = 24;
1209
+ const H5 = 25;
1210
+ const H6 = 26;
1211
+ const Article = 27;
1212
+ const Aside = 28;
1213
+ const Footer = 29;
1214
+ const Header = 30;
1215
+ const Nav = 40;
1216
+ const Section = 41;
1217
+ const Search = 42;
1218
+ const Dd = 43;
1219
+ const Dl = 44;
1220
+ const Figcaption = 45;
1221
+ const Figure = 46;
1222
+ const Hr = 47;
1223
+ const Li = 48;
1224
+ const Ol = 49;
1225
+ const P = 50;
1226
+ const Pre = 51;
1227
+ const A = 53;
1228
+ const Abbr = 54;
1229
+ const Br = 55;
1230
+ const Cite = 56;
1231
+ const Data = 57;
1232
+ const Time = 58;
1233
+ const Tfoot = 59;
1234
+ const Ul = 60;
1235
+ const Video = 61;
1236
+ const TextArea = 62;
1237
+ const Select = 63;
1238
+ const Option$1 = 64;
1239
+ const Code = 65;
1240
+ const Label$1 = 66;
1241
+ const Dt = 67;
1242
+ const Iframe = 68;
1243
+ const Main = 69;
1244
+ const Strong = 70;
1245
+ const Em = 71;
1246
+ const Style = 72;
1247
+ const Html = 73;
1248
+ const Head = 74;
1249
+ const Title = 75;
1250
+ const Meta = 76;
1251
+ const Canvas = 77;
1252
+ const Form = 78;
1253
+ const BlockQuote = 79;
1254
+ const Quote = 80;
1255
+ const Circle = 81;
1256
+ const Defs = 82;
1257
+ const Ellipse = 83;
1258
+ const G = 84;
1259
+ const Line = 85;
1260
+ const Path = 86;
1261
+ const Polygon = 87;
1262
+ const Polyline = 88;
1263
+ const Rect = 89;
1264
+ const Svg = 90;
1265
+ const Use = 91;
1190
1266
  const Reference = 100;
1191
1267
 
1268
+ const VirtualDomElements = {
1269
+ __proto__: null,
1270
+ A,
1271
+ Abbr,
1272
+ Article,
1273
+ Aside,
1274
+ Audio,
1275
+ BlockQuote,
1276
+ Br,
1277
+ Button,
1278
+ Canvas,
1279
+ Circle,
1280
+ Cite,
1281
+ Code,
1282
+ Col,
1283
+ ColGroup,
1284
+ Data,
1285
+ Dd,
1286
+ Defs,
1287
+ Del,
1288
+ Div,
1289
+ Dl,
1290
+ Dt,
1291
+ Ellipse,
1292
+ Em,
1293
+ Figcaption,
1294
+ Figure,
1295
+ Footer,
1296
+ Form,
1297
+ G,
1298
+ H1,
1299
+ H2,
1300
+ H3,
1301
+ H4,
1302
+ H5,
1303
+ H6,
1304
+ Head,
1305
+ Header,
1306
+ Hr,
1307
+ Html,
1308
+ I,
1309
+ Iframe,
1310
+ Img,
1311
+ Input,
1312
+ Ins,
1313
+ Kbd,
1314
+ Label: Label$1,
1315
+ Li,
1316
+ Line,
1317
+ Main,
1318
+ Meta,
1319
+ Nav,
1320
+ Ol,
1321
+ Option: Option$1,
1322
+ P,
1323
+ Path,
1324
+ Polygon,
1325
+ Polyline,
1326
+ Pre,
1327
+ Quote,
1328
+ Rect,
1329
+ Reference,
1330
+ Root,
1331
+ Search,
1332
+ Section,
1333
+ Select,
1334
+ Span,
1335
+ Strong,
1336
+ Style,
1337
+ Svg,
1338
+ TBody,
1339
+ THead,
1340
+ Table,
1341
+ Td,
1342
+ Text,
1343
+ TextArea,
1344
+ Tfoot,
1345
+ Th,
1346
+ Time,
1347
+ Title,
1348
+ Tr,
1349
+ Ul,
1350
+ Use,
1351
+ Video
1352
+ };
1353
+
1192
1354
  const EditorWorker = 99;
1193
1355
  const ExtensionManagementWorker = 9006;
1194
1356
  const RendererProcess = 1670;
@@ -1366,9 +1528,19 @@ const toCommandId = key => {
1366
1528
  return key.slice(dotIndex + 1);
1367
1529
  };
1368
1530
  const create$2 = () => {
1531
+ const commandQueues = new Map();
1532
+ const generations = Object.create(null);
1369
1533
  const states = Object.create(null);
1370
- const commandMapRef = {};
1371
- const updateState = (uid, updater) => {
1534
+ const commandMapRef = Object.create(null);
1535
+ const commandsById = Object.create(null);
1536
+ const getGeneration = uid => generations[uid] || 0;
1537
+ const isCurrentGeneration = (uid, generation) => {
1538
+ return states[uid] !== undefined && getGeneration(uid) === generation;
1539
+ };
1540
+ const updateState = (uid, generation, fallbackState, updater) => {
1541
+ if (!isCurrentGeneration(uid, generation)) {
1542
+ return Promise.resolve(fallbackState);
1543
+ }
1372
1544
  const current = states[uid];
1373
1545
  const updatedState = updater(current.newState);
1374
1546
  if (updatedState !== current.newState) {
@@ -1380,12 +1552,60 @@ const create$2 = () => {
1380
1552
  }
1381
1553
  return Promise.resolve(updatedState);
1382
1554
  };
1555
+ const createAsyncCommandContext = (uid, generation) => {
1556
+ let latestState = states[uid].newState;
1557
+ return {
1558
+ getState: () => {
1559
+ if (isCurrentGeneration(uid, generation)) {
1560
+ latestState = states[uid].newState;
1561
+ }
1562
+ return latestState;
1563
+ },
1564
+ updateState: async updater => {
1565
+ latestState = await updateState(uid, generation, latestState, updater);
1566
+ return latestState;
1567
+ }
1568
+ };
1569
+ };
1570
+ const enqueueCommand = async (uid, command) => {
1571
+ const previous = commandQueues.get(uid) || Promise.resolve();
1572
+ const run = async () => {
1573
+ try {
1574
+ await previous;
1575
+ } catch {
1576
+ // The previous caller receives its error; later commands must still run.
1577
+ }
1578
+ await command();
1579
+ };
1580
+ const current = run();
1581
+ commandQueues.set(uid, current);
1582
+ try {
1583
+ await current;
1584
+ } finally {
1585
+ if (commandQueues.get(uid) === current) {
1586
+ commandQueues.delete(uid);
1587
+ }
1588
+ }
1589
+ };
1383
1590
  return {
1384
1591
  clear() {
1592
+ commandQueues.clear();
1385
1593
  for (const key of Object.keys(states)) {
1386
1594
  delete states[key];
1387
1595
  }
1388
1596
  },
1597
+ createDirectEventCommandMap(requestRender) {
1598
+ return {
1599
+ async 'Viewlet.executeViewletCommand'(uid, command, ...args) {
1600
+ const fn = commandsById[command];
1601
+ if (!fn) {
1602
+ throw new Error(`Viewlet command not found: ${command}`);
1603
+ }
1604
+ await fn(uid, ...args);
1605
+ await requestRender(uid);
1606
+ }
1607
+ };
1608
+ },
1389
1609
  diff(uid, modules, numbers) {
1390
1610
  const {
1391
1611
  oldState,
@@ -1401,6 +1621,7 @@ const create$2 = () => {
1401
1621
  return diffResult;
1402
1622
  },
1403
1623
  dispose(uid) {
1624
+ commandQueues.delete(uid);
1404
1625
  delete states[uid];
1405
1626
  },
1406
1627
  get(uid) {
@@ -1416,8 +1637,15 @@ const create$2 = () => {
1416
1637
  },
1417
1638
  registerCommands(commandMap) {
1418
1639
  Object.assign(commandMapRef, commandMap);
1640
+ for (const [key, fn] of Object.entries(commandMap)) {
1641
+ commandsById[toCommandId(key)] = fn;
1642
+ }
1419
1643
  },
1420
1644
  set(uid, oldState, newState, scheduledState) {
1645
+ const current = states[uid];
1646
+ if (!current || oldState === newState && newState !== current.newState) {
1647
+ generations[uid] = getGeneration(uid) + 1;
1648
+ }
1421
1649
  states[uid] = {
1422
1650
  newState,
1423
1651
  oldState,
@@ -1426,16 +1654,15 @@ const create$2 = () => {
1426
1654
  },
1427
1655
  wrapAsyncCommand(fn) {
1428
1656
  const wrapped = async (uid, ...args) => {
1429
- const context = {
1430
- getState: () => states[uid].newState,
1431
- updateState: updater => updateState(uid, updater)
1432
- };
1657
+ const generation = getGeneration(uid);
1658
+ const context = createAsyncCommandContext(uid, generation);
1433
1659
  await fn(context, ...args);
1434
1660
  };
1435
1661
  return wrapped;
1436
1662
  },
1437
1663
  wrapCommand(fn) {
1438
1664
  const wrapped = async (uid, ...args) => {
1665
+ const generation = getGeneration(uid);
1439
1666
  const {
1440
1667
  newState,
1441
1668
  oldState
@@ -1444,6 +1671,9 @@ const create$2 = () => {
1444
1671
  if (oldState === newerState || newState === newerState) {
1445
1672
  return;
1446
1673
  }
1674
+ if (!isCurrentGeneration(uid, generation)) {
1675
+ return;
1676
+ }
1447
1677
  const latestOld = states[uid];
1448
1678
  const latestNew = {
1449
1679
  ...latestOld.newState,
@@ -1468,6 +1698,7 @@ const create$2 = () => {
1468
1698
  },
1469
1699
  wrapLoadContent(fn) {
1470
1700
  const wrapped = async (uid, ...args) => {
1701
+ const generation = getGeneration(uid);
1471
1702
  const {
1472
1703
  newState,
1473
1704
  oldState
@@ -1482,6 +1713,11 @@ const create$2 = () => {
1482
1713
  error
1483
1714
  };
1484
1715
  }
1716
+ if (!isCurrentGeneration(uid, generation)) {
1717
+ return {
1718
+ error
1719
+ };
1720
+ }
1485
1721
  const latestOld = states[uid];
1486
1722
  const latestNew = {
1487
1723
  ...latestOld.newState,
@@ -1497,6 +1733,51 @@ const create$2 = () => {
1497
1733
  };
1498
1734
  };
1499
1735
  return wrapped;
1736
+ },
1737
+ wrapSerialAsyncCommand(fn) {
1738
+ const wrapped = async (uid, ...args) => {
1739
+ await enqueueCommand(uid, async () => {
1740
+ if (!states[uid]) {
1741
+ return;
1742
+ }
1743
+ const generation = getGeneration(uid);
1744
+ const context = createAsyncCommandContext(uid, generation);
1745
+ await fn(context, ...args);
1746
+ });
1747
+ };
1748
+ return wrapped;
1749
+ },
1750
+ wrapSerialCommand(fn) {
1751
+ const wrapped = async (uid, ...args) => {
1752
+ await enqueueCommand(uid, async () => {
1753
+ if (!states[uid]) {
1754
+ return;
1755
+ }
1756
+ const generation = getGeneration(uid);
1757
+ const {
1758
+ newState,
1759
+ oldState
1760
+ } = states[uid];
1761
+ const newerState = await fn(newState, ...args);
1762
+ if (oldState === newerState || newState === newerState) {
1763
+ return;
1764
+ }
1765
+ if (!isCurrentGeneration(uid, generation)) {
1766
+ return;
1767
+ }
1768
+ const latestOld = states[uid];
1769
+ const latestNew = {
1770
+ ...latestOld.newState,
1771
+ ...newerState
1772
+ };
1773
+ states[uid] = {
1774
+ newState: latestNew,
1775
+ oldState: latestOld.oldState,
1776
+ scheduledState: latestNew
1777
+ };
1778
+ });
1779
+ };
1780
+ return wrapped;
1500
1781
  }
1501
1782
  };
1502
1783
  };
@@ -2198,17 +2479,14 @@ const isUpperCase = char => {
2198
2479
  const isGap = (columnCharBefore, columnChar) => {
2199
2480
  switch (columnCharBefore) {
2200
2481
  case Dash:
2201
- case Underline:
2482
+ case Dot:
2202
2483
  case EmptyString:
2203
- case T:
2204
2484
  case Space:
2205
- case Dot:
2485
+ case T:
2486
+ case Underline:
2206
2487
  return true;
2207
2488
  }
2208
- if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
2209
- return true;
2210
- }
2211
- return false;
2489
+ return isLowerCase(columnCharBefore) && isUpperCase(columnChar);
2212
2490
  };
2213
2491
 
2214
2492
  // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
@@ -2246,6 +2524,15 @@ const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, w
2246
2524
 
2247
2525
  // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
2248
2526
  const traceHighlights = (table, arrows, patternLength, wordLength) => {
2527
+ const skipLeft = (rowStart, columnStart) => {
2528
+ let row = rowStart;
2529
+ let column = columnStart;
2530
+ while (row >= 1 && column >= 1 && arrows[row][column] === Diagonal) {
2531
+ row--;
2532
+ column--;
2533
+ }
2534
+ return [row, column];
2535
+ };
2249
2536
  let row = patternLength;
2250
2537
  let column = wordLength;
2251
2538
  const matches = [];
@@ -2253,23 +2540,14 @@ const traceHighlights = (table, arrows, patternLength, wordLength) => {
2253
2540
  const arrow = arrows[row][column];
2254
2541
  if (arrow === Left) {
2255
2542
  column--;
2256
- } else if (arrow === Diagonal) {
2257
- row--;
2258
- column--;
2259
- const start = column + 1;
2260
- while (row >= 1 && column >= 1) {
2261
- const arrow = arrows[row][column];
2262
- if (arrow === Left) {
2263
- break;
2264
- }
2265
- if (arrow === Diagonal) {
2266
- row--;
2267
- column--;
2268
- }
2269
- }
2270
- const end = column;
2271
- matches.unshift(end, start);
2543
+ continue;
2272
2544
  }
2545
+ if (arrow !== Diagonal) {
2546
+ break;
2547
+ }
2548
+ const start = column;
2549
+ [row, column] = skipLeft(row - 1, column - 1);
2550
+ matches.unshift(column, start);
2273
2551
  }
2274
2552
  matches.unshift(table[patternLength][wordLength - 1]);
2275
2553
  return matches;
@@ -2279,6 +2557,38 @@ const traceHighlights = (table, arrows, patternLength, wordLength) => {
2279
2557
  const gridSize = 128;
2280
2558
  const table = createTable(gridSize);
2281
2559
  const arrows = createTable(gridSize);
2560
+ const fillRow = (row, pattern, patternLower, word, wordLower, table, arrows, wordLength) => {
2561
+ const rowChar = pattern[row - 1];
2562
+ const rowCharLow = patternLower[row - 1];
2563
+ let strongMatch = false;
2564
+ for (let column = 1; column < wordLength + 1; column++) {
2565
+ const columnChar = word[column - 1];
2566
+ const columnCharLow = wordLower[column - 1];
2567
+ const columnCharBefore = word[column - 2] || '';
2568
+ const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
2569
+ const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch);
2570
+ strongMatch ||= score > 5;
2571
+ let diagonalScore = score + table[row - 1][column - 1];
2572
+ if (isDiagonalMatch && score !== -1) {
2573
+ diagonalScore += 2;
2574
+ }
2575
+ const leftScore = table[row][column - 1];
2576
+ const useLeft = leftScore > diagonalScore;
2577
+ table[row][column] = useLeft ? leftScore : diagonalScore;
2578
+ arrows[row][column] = useLeft ? Left : Diagonal;
2579
+ }
2580
+ return strongMatch;
2581
+ };
2582
+ const fillTable = (pattern, patternLower, word, wordLower, table, arrows, patternLength, wordLength) => {
2583
+ let strongMatch = false;
2584
+ for (let row = 1; row < patternLength + 1; row++) {
2585
+ const isMatch = fillRow(row, pattern, patternLower, word, wordLower, table, arrows, wordLength);
2586
+ if (row === 1) {
2587
+ strongMatch ||= isMatch;
2588
+ }
2589
+ }
2590
+ return strongMatch;
2591
+ };
2282
2592
  const fuzzySearch = (pattern, word) => {
2283
2593
  const patternLength = Math.min(pattern.length, gridSize - 1);
2284
2594
  const wordLength = Math.min(word.length, gridSize - 1);
@@ -2287,33 +2597,7 @@ const fuzzySearch = (pattern, word) => {
2287
2597
  if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
2288
2598
  return EmptyMatches;
2289
2599
  }
2290
- let strongMatch = false;
2291
- for (let row = 1; row < patternLength + 1; row++) {
2292
- const rowChar = pattern[row - 1];
2293
- const rowCharLow = patternLower[row - 1];
2294
- for (let column = 1; column < wordLength + 1; column++) {
2295
- const columnChar = word[column - 1];
2296
- const columnCharLow = wordLower[column - 1];
2297
- const columnCharBefore = word[column - 2] || '';
2298
- const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
2299
- const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch);
2300
- if (row === 1 && score > 5) {
2301
- strongMatch = true;
2302
- }
2303
- let diagonalScore = score + table[row - 1][column - 1];
2304
- if (isDiagonalMatch && score !== -1) {
2305
- diagonalScore += 2;
2306
- }
2307
- const leftScore = table[row][column - 1];
2308
- if (leftScore > diagonalScore) {
2309
- table[row][column] = leftScore;
2310
- arrows[row][column] = Left;
2311
- } else {
2312
- table[row][column] = diagonalScore;
2313
- arrows[row][column] = Diagonal;
2314
- }
2315
- }
2316
- }
2600
+ const strongMatch = fillTable(pattern, patternLower, word, wordLower, table, arrows, patternLength, wordLength);
2317
2601
  if (!strongMatch) {
2318
2602
  return EmptyMatches;
2319
2603
  }
@@ -2760,15 +3044,15 @@ const getPosition = (text, wantedColumn) => {
2760
3044
  };
2761
3045
 
2762
3046
  const emptyObject = {};
2763
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
2764
3047
  const i18nString = (key, placeholders = emptyObject) => {
2765
3048
  if (placeholders === emptyObject) {
2766
3049
  return key;
2767
3050
  }
2768
- const replacer = (match, rest) => {
2769
- return placeholders[rest];
2770
- };
2771
- return key.replaceAll(RE_PLACEHOLDER, replacer);
3051
+ let result = key;
3052
+ for (const [placeholder, replacement] of Object.entries(placeholders)) {
3053
+ result = result.split(`{${placeholder}}`).join(String(replacement));
3054
+ }
3055
+ return result;
2772
3056
  };
2773
3057
 
2774
3058
  const GoToFile = 'Go to file';
@@ -3989,6 +4273,8 @@ const text = data => {
3989
4273
  };
3990
4274
  };
3991
4275
 
4276
+ new Set(Object.values(VirtualDomElements));
4277
+
3992
4278
  const SetText = 1;
3993
4279
  const Replace = 2;
3994
4280
  const SetAttribute = 3;
@@ -4060,21 +4346,18 @@ const getChildrenWithCount = (nodes, startIndex, childCount) => {
4060
4346
  };
4061
4347
 
4062
4348
  const compareNodes = (oldNode, newNode) => {
4063
- const patches = [];
4064
4349
  // Check if node type changed - return null to signal incompatible nodes
4065
4350
  // (caller should handle this with a Replace operation)
4066
4351
  if (oldNode.type !== newNode.type) {
4067
4352
  return null;
4068
4353
  }
4354
+ const patches = [];
4069
4355
  // Handle reference nodes - special handling for uid changes
4070
- if (oldNode.type === Reference) {
4071
- if (oldNode.uid !== newNode.uid) {
4072
- patches.push({
4073
- type: SetReferenceNodeUid,
4074
- uid: newNode.uid
4075
- });
4076
- }
4077
- return patches;
4356
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
4357
+ patches.push({
4358
+ type: SetReferenceNodeUid,
4359
+ uid: newNode.uid
4360
+ });
4078
4361
  }
4079
4362
  // Handle text nodes
4080
4363
  if (oldNode.type === Text && newNode.type === Text) {
@@ -4087,8 +4370,8 @@ const compareNodes = (oldNode, newNode) => {
4087
4370
  return patches;
4088
4371
  }
4089
4372
  // Compare attributes
4090
- const oldKeys = getKeys(oldNode);
4091
- const newKeys = getKeys(newNode);
4373
+ const oldKeys = getKeys(oldNode).filter(key => oldNode.type !== Reference || key !== 'uid');
4374
+ const newKeys = getKeys(newNode).filter(key => newNode.type !== Reference || key !== 'uid');
4092
4375
  // Check for attribute changes
4093
4376
  for (const key of newKeys) {
4094
4377
  if (oldNode[key] !== newNode[key]) {
@@ -4101,7 +4384,7 @@ const compareNodes = (oldNode, newNode) => {
4101
4384
  }
4102
4385
  // Check for removed attributes
4103
4386
  for (const key of oldKeys) {
4104
- if (!(key in newNode)) {
4387
+ if (!Object.hasOwn(newNode, key)) {
4105
4388
  patches.push({
4106
4389
  type: RemoveAttribute,
4107
4390
  key
@@ -4112,18 +4395,90 @@ const compareNodes = (oldNode, newNode) => {
4112
4395
  };
4113
4396
 
4114
4397
  const treeToArray = node => {
4115
- const result = [node.node];
4116
- for (const child of node.children) {
4117
- result.push(...treeToArray(child));
4398
+ const result = [];
4399
+ const stack = [node];
4400
+ while (stack.length > 0) {
4401
+ const current = stack.pop();
4402
+ result.push(current.node);
4403
+ for (let i = current.children.length - 1; i >= 0; i--) {
4404
+ stack.push(current.children[i]);
4405
+ }
4118
4406
  }
4119
4407
  return result;
4120
4408
  };
4121
4409
 
4410
+ const navigateToChild = (patches, currentChildIndex, index) => {
4411
+ if (currentChildIndex === -1) {
4412
+ patches.push({
4413
+ type: NavigateChild,
4414
+ index
4415
+ });
4416
+ return index;
4417
+ }
4418
+ if (currentChildIndex !== index) {
4419
+ patches.push({
4420
+ type: NavigateSibling,
4421
+ index
4422
+ });
4423
+ }
4424
+ return index;
4425
+ };
4426
+ const navigateToParent = (patches, currentChildIndex) => {
4427
+ if (currentChildIndex >= 0) {
4428
+ patches.push({
4429
+ type: NavigateParent
4430
+ });
4431
+ }
4432
+ return -1;
4433
+ };
4434
+ const addTree = (newNode, patches) => {
4435
+ patches.push({
4436
+ type: Add,
4437
+ nodes: treeToArray(newNode)
4438
+ });
4439
+ };
4440
+ const replaceTree = (newNode, patches) => {
4441
+ patches.push({
4442
+ type: Replace,
4443
+ nodes: treeToArray(newNode)
4444
+ });
4445
+ };
4446
+ const diffExistingChild = (oldNode, newNode, patches, currentChildIndex, index) => {
4447
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
4448
+ if (nodePatches === null) {
4449
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
4450
+ replaceTree(newNode, patches);
4451
+ return nextChildIndex;
4452
+ }
4453
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
4454
+ if (nodePatches.length === 0 && !hasChildrenToCompare) {
4455
+ return currentChildIndex;
4456
+ }
4457
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
4458
+ if (nodePatches.length > 0) {
4459
+ patches.push(...nodePatches);
4460
+ }
4461
+ if (hasChildrenToCompare) {
4462
+ diffChildren(oldNode.children, newNode.children, patches);
4463
+ }
4464
+ return nextChildIndex;
4465
+ };
4466
+ const diffRootNode = (oldNode, newNode, patches) => {
4467
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
4468
+ if (nodePatches === null) {
4469
+ replaceTree(newNode, patches);
4470
+ return;
4471
+ }
4472
+ if (nodePatches.length > 0) {
4473
+ patches.push(...nodePatches);
4474
+ }
4475
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
4476
+ diffChildren(oldNode.children, newNode.children, patches);
4477
+ }
4478
+ };
4122
4479
  const diffChildren = (oldChildren, newChildren, patches) => {
4123
4480
  const maxLength = Math.max(oldChildren.length, newChildren.length);
4124
- // Track where we are: -1 means at parent, >= 0 means at child index
4125
4481
  let currentChildIndex = -1;
4126
- // Collect indices of children to remove (we'll add these patches at the end in reverse order)
4127
4482
  const indicesToRemove = [];
4128
4483
  for (let i = 0; i < maxLength; i++) {
4129
4484
  const oldNode = oldChildren[i];
@@ -4132,88 +4487,17 @@ const diffChildren = (oldChildren, newChildren, patches) => {
4132
4487
  continue;
4133
4488
  }
4134
4489
  if (!oldNode) {
4135
- // Add new node - we should be at the parent
4136
- if (currentChildIndex >= 0) {
4137
- // Navigate back to parent
4138
- patches.push({
4139
- type: NavigateParent
4140
- });
4141
- currentChildIndex = -1;
4142
- }
4143
- // Flatten the entire subtree so renderInternal can handle it
4144
- const flatNodes = treeToArray(newNode);
4145
- patches.push({
4146
- type: Add,
4147
- nodes: flatNodes
4148
- });
4149
- } else if (newNode) {
4150
- // Compare nodes to see if we need any patches
4151
- const nodePatches = compareNodes(oldNode.node, newNode.node);
4152
- // If nodePatches is null, the node types are incompatible - need to replace
4153
- if (nodePatches === null) {
4154
- // Navigate to this child
4155
- if (currentChildIndex === -1) {
4156
- patches.push({
4157
- type: NavigateChild,
4158
- index: i
4159
- });
4160
- currentChildIndex = i;
4161
- } else if (currentChildIndex !== i) {
4162
- patches.push({
4163
- type: NavigateSibling,
4164
- index: i
4165
- });
4166
- currentChildIndex = i;
4167
- }
4168
- // Replace the entire subtree
4169
- const flatNodes = treeToArray(newNode);
4170
- patches.push({
4171
- type: Replace,
4172
- nodes: flatNodes
4173
- });
4174
- // After replace, we're at the new element (same position)
4175
- continue;
4176
- }
4177
- // Check if we need to recurse into children
4178
- const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
4179
- // Only navigate to this element if we need to do something
4180
- if (nodePatches.length > 0 || hasChildrenToCompare) {
4181
- // Navigate to this child if not already there
4182
- if (currentChildIndex === -1) {
4183
- patches.push({
4184
- type: NavigateChild,
4185
- index: i
4186
- });
4187
- currentChildIndex = i;
4188
- } else if (currentChildIndex !== i) {
4189
- patches.push({
4190
- type: NavigateSibling,
4191
- index: i
4192
- });
4193
- currentChildIndex = i;
4194
- }
4195
- // Apply node patches (these apply to the current element, not children)
4196
- if (nodePatches.length > 0) {
4197
- patches.push(...nodePatches);
4198
- }
4199
- // Compare children recursively
4200
- if (hasChildrenToCompare) {
4201
- diffChildren(oldNode.children, newNode.children, patches);
4202
- }
4203
- }
4204
- } else {
4205
- // Remove old node - collect the index for later removal
4490
+ currentChildIndex = navigateToParent(patches, currentChildIndex);
4491
+ addTree(newNode, patches);
4492
+ continue;
4493
+ }
4494
+ if (!newNode) {
4206
4495
  indicesToRemove.push(i);
4496
+ continue;
4207
4497
  }
4498
+ currentChildIndex = diffExistingChild(oldNode, newNode, patches, currentChildIndex, i);
4208
4499
  }
4209
- // Navigate back to parent if we ended at a child
4210
- if (currentChildIndex >= 0) {
4211
- patches.push({
4212
- type: NavigateParent
4213
- });
4214
- }
4215
- // Add remove patches in reverse order (highest index first)
4216
- // This ensures indices remain valid as we remove
4500
+ navigateToParent(patches, currentChildIndex);
4217
4501
  for (let j = indicesToRemove.length - 1; j >= 0; j--) {
4218
4502
  patches.push({
4219
4503
  type: RemoveChild,
@@ -4222,47 +4506,22 @@ const diffChildren = (oldChildren, newChildren, patches) => {
4222
4506
  }
4223
4507
  };
4224
4508
  const diffTrees = (oldTree, newTree, patches, path) => {
4225
- // At the root level (path.length === 0), we're already AT the element
4226
- // So we compare the root node directly, then compare its children
4227
4509
  if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
4228
- const oldNode = oldTree[0];
4229
- const newNode = newTree[0];
4230
- // Compare root nodes
4231
- const nodePatches = compareNodes(oldNode.node, newNode.node);
4232
- // If nodePatches is null, the root node types are incompatible - need to replace
4233
- if (nodePatches === null) {
4234
- const flatNodes = treeToArray(newNode);
4235
- patches.push({
4236
- type: Replace,
4237
- nodes: flatNodes
4238
- });
4239
- return;
4240
- }
4241
- if (nodePatches.length > 0) {
4242
- patches.push(...nodePatches);
4243
- }
4244
- // Compare children
4245
- if (oldNode.children.length > 0 || newNode.children.length > 0) {
4246
- diffChildren(oldNode.children, newNode.children, patches);
4247
- }
4248
- } else {
4249
- // Non-root level or multiple root elements - use the regular comparison
4250
- diffChildren(oldTree, newTree, patches);
4510
+ diffRootNode(oldTree[0], newTree[0], patches);
4511
+ return;
4251
4512
  }
4513
+ diffChildren(oldTree, newTree, patches);
4252
4514
  };
4253
4515
 
4254
4516
  const removeTrailingNavigationPatches = patches => {
4255
- // Find the last non-navigation patch
4256
- let lastNonNavigationIndex = -1;
4257
- for (let i = patches.length - 1; i >= 0; i--) {
4258
- const patch = patches[i];
4517
+ while (patches.length > 0) {
4518
+ const patch = patches.at(-1);
4259
4519
  if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
4260
- lastNonNavigationIndex = i;
4261
4520
  break;
4262
4521
  }
4522
+ patches.pop();
4263
4523
  }
4264
- // Return patches up to and including the last non-navigation patch
4265
- return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
4524
+ return patches;
4266
4525
  };
4267
4526
 
4268
4527
  const diffTree = (oldNodes, newNodes) => {
@@ -4804,6 +5063,30 @@ const selectItem = async (state, label) => {
4804
5063
  return selectIndex(state, index);
4805
5064
  };
4806
5065
 
5066
+ const queues = new Map();
5067
+ const serialize = command => {
5068
+ return async (uid, ...args) => {
5069
+ const previous = queues.get(uid) || Promise.resolve();
5070
+ const run = async () => {
5071
+ try {
5072
+ await previous;
5073
+ } catch {
5074
+ // The previous caller receives its error; later commands must still run.
5075
+ }
5076
+ await command(uid, ...args);
5077
+ };
5078
+ const current = run();
5079
+ queues.set(uid, current);
5080
+ try {
5081
+ await current;
5082
+ } finally {
5083
+ if (queues.get(uid) === current) {
5084
+ queues.delete(uid);
5085
+ }
5086
+ }
5087
+ };
5088
+ };
5089
+
4807
5090
  const showQuickInput = async ({
4808
5091
  id,
4809
5092
  ignoreFocusOut,
@@ -4882,7 +5165,7 @@ const commandMap = {
4882
5165
  'QuickPick.handleBlur': wrapCommand(handleBlur),
4883
5166
  'QuickPick.handleClickAt': wrapCommand(handleClickAt),
4884
5167
  'QuickPick.handleFocus': wrapCommand(handleFocus),
4885
- 'QuickPick.handleInput': wrapAsyncCommand(handleInputWithContext),
5168
+ 'QuickPick.handleInput': serialize(wrapAsyncCommand(handleInputWithContext)),
4886
5169
  'QuickPick.handleMessagePort': handleMessagePort,
4887
5170
  'QuickPick.handleRendererProcessMessagePort': handleDirectMessagePort,
4888
5171
  'QuickPick.handleScrollBarPointerDown': wrapCommand(handleScrollBarPointerDown),
@@ -4893,7 +5176,7 @@ const commandMap = {
4893
5176
  'QuickPick.loadContent': wrapAsyncCommand(loadContentWithContext),
4894
5177
  'QuickPick.render2': render2,
4895
5178
  'QuickPick.renderEventListeners': renderEventListeners,
4896
- 'QuickPick.selectCurrentIndex': wrapCommand(selectCurrentIndex),
5179
+ 'QuickPick.selectCurrentIndex': serialize(wrapCommand(selectCurrentIndex)),
4897
5180
  'QuickPick.selectIndex': wrapCommand(selectIndex),
4898
5181
  'QuickPick.selectItem': wrapCommand(selectItem),
4899
5182
  'QuickPick.setDeltaY': wrapCommand(setDeltaY),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/quick-pick-worker",
3
- "version": "4.18.0",
3
+ "version": "4.19.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/lvce-editor/quick-pick-worker.git"