Skip to content

Commit

Permalink
perf: improve RefStateEditor.set performance (#221)
Browse files Browse the repository at this point in the history
  • Loading branch information
Azurewarth0920 authored Feb 4, 2024
1 parent 5ce3a00 commit 112ecb7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { RefStateEditor } from '../editor'

describe('editor: RefStateEditor', () => {
const editor = new RefStateEditor()

// eslint-disable-next-line test/consistent-test-it
test.each([
// Add new key.
{ refValue: { foo: 'bar' }, newValue: { foo: 'bar', bar: 'baz' } },
// Add new key and modify origin value.
{ refValue: { foo: 'bar' }, newValue: { foo: 'barr', bar: 'baz' } },
// Modify origin value.
{ refValue: { foo: 'bar' }, newValue: { foo: 'barr' } },
// Remove key.
{ refValue: { foo: 'bar' }, newValue: {} },
// Remove key and modify origin value.
{ refValue: { foo: 'bar' }, newValue: { foo: 'barr' } },
// Remove key and add new key.
{ refValue: { foo: 'bar' }, newValue: { bar: 'baz' } },
])('$refValue can be modified to $newValue by RefStateEditor.set', ({ refValue, newValue }) => {
editor.set(refValue as any, newValue)
expect(refValue).toEqual(newValue)
})
})
11 changes: 4 additions & 7 deletions packages/devtools-kit/src/core/component/state/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,26 +95,23 @@ export class StateEditor {
}
}

class RefStateEditor {
export class RefStateEditor {
set(ref: Ref<any>, value: any): void {
if (isRef(ref)) {
ref.value = value
}
else {
// if is reactive, then it must be object
// to prevent loss reactivity, we should assign key by key
const previousKeys = Object.keys(ref)
const previousKeysSet = new Set(Object.keys(ref))
const currentKeys = Object.keys(value)
// we should check the key diffs, if previous key is the longer
// then remove the needless keys
// @TODO: performance optimization
if (previousKeys.length > currentKeys.length) {
const diffKeys = previousKeys.filter(key => !currentKeys.includes(key))
diffKeys.forEach(key => Reflect.deleteProperty(ref, key))
}
currentKeys.forEach((key) => {
Reflect.set(ref, key, Reflect.get(value, key))
previousKeysSet.delete(key)
})
previousKeysSet.forEach(key => Reflect.deleteProperty(ref, key))
}
}

Expand Down

0 comments on commit 112ecb7

Please sign in to comment.