Skip to content

Commit b8c5eea

Browse files
AbyanzhafranKevinVandyautofix-ci[bot]
authored
fix: Solving Quadratic Slowdown in svelte-table (#6266)
* perf(svelte-table): fix quadratic slowdown by introducing flatMerge in reactive loops * ci: apply automated fixes --------- Co-authored-by: Kevin Van Cott <kevinvandy656@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent d1446e3 commit b8c5eea

2 files changed

Lines changed: 39 additions & 3 deletions

File tree

packages/svelte-table/src/createTable.svelte.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { constructTable } from '@tanstack/table-core'
22
import { useSelector } from '@tanstack/svelte-store'
33
import { untrack } from 'svelte'
4-
import { mergeObjects } from './merge-objects'
4+
import { flatMerge, mergeObjects } from './merge-objects'
55
import { svelteReactivity } from './reactivity.svelte'
66
import type {
77
RowData,
@@ -75,7 +75,7 @@ export function createTable<
7575
defaultOptions: TableOptions<TFeatures, TData>,
7676
newOptions: Partial<TableOptions<TFeatures, TData>>,
7777
) => {
78-
return mergeObjects(defaultOptions, newOptions)
78+
return flatMerge(defaultOptions, newOptions)
7979
},
8080
},
8181
mergedOptions,
@@ -107,7 +107,7 @@ export function createTable<
107107

108108
untrack(() => {
109109
table.setOptions((prev) => {
110-
return mergeObjects(prev, mergedOptions)
110+
return flatMerge(prev, mergedOptions)
111111
})
112112
})
113113
})

packages/svelte-table/src/merge-objects.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,39 @@ export function mergeObjects(...sources: any): any {
4141
}
4242
return target
4343
}
44+
45+
/**
46+
* Merges objects together by eagerly resolving all values into a flat object.
47+
*
48+
* Unlike `mergeObjects`, this does NOT preserve getters — values are read once
49+
* and stored as plain data properties. This prevents the getter-chain
50+
* accumulation that causes O(N) lookups when the result is repeatedly passed
51+
* back as a source in subsequent merges (e.g., inside `$effect.pre` loops).
52+
*
53+
* Later sources take precedence; `undefined` values do not override.
54+
*
55+
* @see https://github.com/TanStack/table/issues/6235
56+
*/
57+
export function flatMerge<T>(source: T): T
58+
export function flatMerge<T, U>(source: T, source1: U): T & U
59+
export function flatMerge<T, U, V>(source: T, source1: U, source2: V): T & U & V
60+
export function flatMerge<T, U, V, W>(
61+
source: T,
62+
source1: U,
63+
source2: V,
64+
source3: W,
65+
): T & U & V & W
66+
export function flatMerge(...sources: any): any {
67+
const result: Record<PropertyKey, unknown> = {}
68+
for (let source of sources) {
69+
if (typeof source === 'function') source = source()
70+
if (!source) continue
71+
for (const key of Reflect.ownKeys(source)) {
72+
const value = (source as Record<PropertyKey, unknown>)[key]
73+
if (value !== undefined) {
74+
result[key as string] = value
75+
}
76+
}
77+
}
78+
return result
79+
}

0 commit comments

Comments
 (0)