Skip to content

Commit 882928a

Browse files
committed
fix(language-core): avoid unrelated virtual code recomputes on style change
1 parent 25f40ea commit 882928a

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

packages/language-core/lib/utils/signals.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,19 @@ export function computedSet<T>(source: () => Set<T>): () => Set<T> {
5959
}
6060
);
6161
}
62+
63+
export function computedItems<T>(
64+
source: () => T[],
65+
compareFn: (oldItem: T, newItem: T) => boolean
66+
) {
67+
return computed<T[]>(
68+
oldArr => {
69+
oldArr ??= [];
70+
const newArr = source();
71+
if (oldArr.length === newArr.length && oldArr.every((item, index) => compareFn(item, newArr[index]))) {
72+
return oldArr;
73+
}
74+
return newArr;
75+
}
76+
);
77+
}

packages/language-core/lib/virtualFile/computedSfc.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type * as ts from 'typescript';
55
import type { Sfc, SfcBlock, SfcBlockAttr, VueLanguagePluginReturn } from '../types';
66
import { parseCssClassNames } from '../utils/parseCssClassNames';
77
import { parseCssVars } from '../utils/parseCssVars';
8-
import { computedArray } from '../utils/signals';
8+
import { computedArray, computedItems } from '../utils/signals';
99

1010
export function computedSfc(
1111
ts: typeof import('typescript'),
@@ -116,8 +116,14 @@ export function computedSfc(
116116
const base = computedSfcBlock('style_' + i, 'css', getBlock);
117117
const getModule = computedAttrValue('__module', base, getBlock);
118118
const getScoped = computed(() => !!getBlock().scoped);
119-
const getCssVars = computed(() => [...parseCssVars(base.content)]);
120-
const getClassNames = computed(() => [...parseCssClassNames(base.content)]);
119+
const getCssVars = computedItems(
120+
() => [...parseCssVars(base.content)],
121+
(oldItem, newItem) => oldItem.text === newItem.text && oldItem.offset === newItem.offset
122+
);
123+
const getClassNames = computedItems(
124+
() => [...parseCssClassNames(base.content)],
125+
(oldItem, newItem) => oldItem.text === newItem.text && oldItem.offset === newItem.offset
126+
);
121127
return () => mergeObject(base, {
122128
get module() { return getModule(); },
123129
get scoped() { return getScoped(); },

0 commit comments

Comments
 (0)