39 lines
2.6 KiB
Diff
39 lines
2.6 KiB
Diff
# UNDF: UNDF-2026-000000809
|
||
# UNDF: (leave blank)
|
||
# vscode-0003: userDataSync merge compare() functions O(N×M) array includes
|
||
#
|
||
# Files affected (all same pattern):
|
||
# src/vs/platform/userDataSync/common/extensionsMerge.ts (lines 259-260, 375-376)
|
||
# src/vs/platform/userDataSync/common/settingsMerge.ts (lines 301-302)
|
||
# src/vs/platform/userDataSync/common/globalStateMerge.ts (lines 126-127)
|
||
# src/vs/platform/userDataSync/common/snippetsMerge.ts (lines 156-157)
|
||
# src/vs/platform/userDataSync/common/keybindingsMerge.ts (lines 258-259, 279-280)
|
||
# src/vs/platform/userDataSync/common/promptsSync/promptsMerge.ts (lines 156-157)
|
||
# src/vs/platform/userDataSync/common/userDataProfilesManifestMerge.ts (lines 118-119)
|
||
#
|
||
# Defect: Every compare() function computes set-difference between two key
|
||
# arrays using fromKeys.filter(key => !toKeys.includes(key)) — O(N×M)
|
||
# where N, M = number of keys in each side. Runs on every sync merge.
|
||
# Fix: Convert one side to a Set before filtering. The result is already
|
||
# fed into a Set, so intermediate Set creation is free.
|
||
# Severity: MEDIUM (N = settings/extensions/keybindings count, 100-500)
|
||
# Speedup: 250x at N=500
|
||
#
|
||
# Representative fix for extensionsMerge.ts compare():
|
||
--- a/src/vs/platform/userDataSync/common/extensionsMerge.ts
|
||
+++ b/src/vs/platform/userDataSync/common/extensionsMerge.ts
|
||
@@ -256,8 +256,10 @@
|
||
function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISyncExtension>, ignoredExtensions: Set<string>, checkVersionProperty: boolean): { added: Set<string>; removed: Set<string>; updated: Set<string> } {
|
||
const fromKeys = from ? [...from.keys()].filter(key => !ignoredExtensions.has(key)) : [];
|
||
const toKeys = [...to.keys()].filter(key => !ignoredExtensions.has(key));
|
||
- const added = toKeys.filter(key => !fromKeys.includes(key)).reduce((r, key) => { r.add(key); return r; }, new Set<string>());
|
||
- const removed = fromKeys.filter(key => !toKeys.includes(key)).reduce((r, key) => { r.add(key); return r; }, new Set<string>());
|
||
+ const fromKeysSet = new Set(fromKeys);
|
||
+ const toKeysSet = new Set(toKeys);
|
||
+ const added = toKeys.filter(key => !fromKeysSet.has(key)).reduce((r, key) => { r.add(key); return r; }, new Set<string>());
|
||
+ const removed = fromKeys.filter(key => !toKeysSet.has(key)).reduce((r, key) => { r.add(key); return r; }, new Set<string>());
|
||
const updated: Set<string> = new Set<string>();
|
||
|
||
# Same fix applies to all 7 other compare() call sites listed above.
|
||
# Each instance: replace array.includes() with Set.has() by converting
|
||
# the lookup array to a Set before the filter call.
|