Skip to content

Commit

Permalink
feat(kit): optimize editing on native set (#269)
Browse files Browse the repository at this point in the history
  • Loading branch information
Azurewarth0920 authored Mar 11, 2024
1 parent a5a1aba commit 3addaad
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 8 deletions.
13 changes: 9 additions & 4 deletions packages/client/src/components/inspector/InspectorStateField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,21 @@ const raw = computed(() => getRaw(props.data.value))
const limit = ref(STATE_FIELDS_LIMIT_SIZE)
const normalizedChildField = computed(() => {
const { value, inherit } = raw.value
const normalizedChildField = computed<
Record<string, InspectorState>
>(() => {
const { value, inherit, customType } = raw.value
// The member in native set can only be added or removed.
// It cannot be modified.
const isUneditableType = customType === 'set'
let displayedValue: any[]
if (isArray(value)) {
const sliced = value.slice(0, limit.value)
return sliced.map((item, i) => ({
key: `${props.data.key}.${i}`,
value: item,
...inherit,
editable: props.data.editable,
editable: props.data.editable && !isUneditableType,
creating: false,
}))
}
Expand All @@ -71,7 +76,7 @@ const normalizedChildField = computed(() => {
key: `${props.data.key}.${key}`,
value: value[key],
...inherit,
editable: props.data.editable,
editable: props.data.editable && !isUneditableType,
creating: false,
}))
if (type.value !== 'custom')
Expand Down
158 changes: 157 additions & 1 deletion packages/devtools-kit/__tests__/component/editor.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { RefStateEditor } from '../../src/core/component/state/editor'
import { RefStateEditor, StateEditor } from '../../src/core/component/state/editor'

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

// Plain object
// eslint-disable-next-line test/consistent-test-it
test.each([
// Plain object.
// Add new key.
{ refValue: { foo: 'bar' }, newValue: { foo: 'bar', bar: 'baz' } },
// Add new key and modify origin value.
Expand All @@ -21,4 +23,158 @@ describe('editor: RefStateEditor', () => {
editor.set(refValue as any, newValue)
expect(refValue).toEqual(newValue)
})

// Native set
it('refStateEditor.set on native set', () => {
const refValue = new Set(['foo', 'bar'])
const newValue = ['baz', 'foo', 'bar']
const targetValue = new Set(['baz', 'foo', 'bar'])
editor.set(refValue as any, newValue)
expect(refValue).toEqual(targetValue)
})

// Native map
// eslint-disable-next-line test/consistent-test-it
test.each([
// Add new key.
{ refValue: new Map([['foo', 'bar']]), newValue: { foo: 'bar', bar: 'baz' }, targetValue: new Map([['foo', 'bar'], ['bar', 'baz']]) },
// Add new key and modify origin value.
{ refValue: new Map([['foo', 'bar']]), newValue: { foo: 'barr', bar: 'baz' }, targetValue: new Map([['foo', 'barr'], ['bar', 'baz']]) },
// Add new key and modify origin value.
{ refValue: new Map([['foo', 'bar']]), newValue: { foo: 'barr', bar: 'baz' }, targetValue: new Map([['foo', 'barr'], ['bar', 'baz']]) },
// Modify origin value.
{ refValue: new Map([['foo', 'bar']]), newValue: { foo: 'barr' }, targetValue: new Map([['foo', 'barr']]) },
// Remove key.
{ refValue: new Map([['foo', 'bar']]), newValue: {}, targetValue: new Map() },
// Remove key and modify origin value.
{ refValue: new Map([['foo', 'bar']]), newValue: { foo: 'barr' }, targetValue: new Map([['foo', 'barr']]) },
// Remove key and add new key.
{ refValue: new Map([['foo', 'bar']]), newValue: { bar: 'baz' }, targetValue: new Map([['bar', 'baz']]) },
])('%o can be modified to $newValue by RefStateEditor.set', ({ refValue, newValue, targetValue }) => {
editor.set(refValue as any, newValue)
expect(refValue).toEqual(targetValue || newValue)
})
})

describe('editor: StateEditor.set', () => {
const stateEditor = new StateEditor()

describe('editComponentState: plain object', () => {
it('modify value', () => {
const target = { foo: 'bar' }
const newValue = 'baz'
const state = { newKey: '', type: '', value: 'baz' }
const path = 'foo'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, newValue, defaultCallback)
expect(target).toEqual({ foo: 'baz' })
})

it('add new value', () => {
const target = { foo: 'bar' }
const newValue = 'baz'
const state = { newKey: 'bar', type: '', value: 'baz' }
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, '', newValue, defaultCallback)
expect(target).toEqual({ foo: 'bar', bar: 'baz' })
})

it('remove value', () => {
const target = { foo: 'bar', bar: 'baz' }
const state = { newKey: '', type: '', value: '', remove: true }
const path = 'foo'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, '', defaultCallback)
expect(target).toEqual({ bar: 'baz' })
})
})

describe('editComponentState: array', () => {
it('modify value', () => {
const target = ['foo', 'bar']
const state = { newKey: '', type: '', value: 'baz' }
const newValue = 'baz'
const path = '0'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, newValue, defaultCallback)
expect(target).toEqual(['baz', 'bar'])
})

it('add new value', () => {
const target = ['foo', 'bar']
const newValue = 'baz'
const state = { newKey: '2', type: '', value: newValue }
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, '2', newValue, defaultCallback)
expect(target).toEqual(['foo', 'bar', 'baz'])
})

it('remove value', () => {
const target = ['foo', 'bar', 'baz']
const state = { newKey: '', type: '', value: '', remove: true }
const path = '0'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, '', defaultCallback)
expect(target).toEqual(['bar', 'baz'])
})
})

describe('editComponentState: set', () => {
it('add new value', () => {
const target = new Set(['foo', 'bar'])
const newValue = 'baz'
const state = { newKey: '2', type: '', value: newValue }
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, '2', newValue, defaultCallback)
expect(target).toEqual(new Set(['foo', 'bar', 'baz']))
})

it('remove value', () => {
const target = new Set(['foo', 'bar', 'baz'])
const state = { newKey: '', type: '', value: 'foo', remove: true }
const path = '0'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, '', defaultCallback)
expect(target).toEqual(new Set(['bar', 'baz']))
})

it('remove object type member', () => {
const target = new Set(['foo', { bar: 'baz' }])
const state = { newKey: '', type: '', value: { bar: 'baz' }, remove: true }
const path = '1'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, '', defaultCallback)
expect(target).toEqual(new Set(['foo']))
})
})

describe('editComponentState: map', () => {
it('modify value', () => {
const target = new Map([['foo', 'bar']])
const state = { newKey: '', type: '', value: 'baz' }
const newValue = 'baz'
const path = 'foo'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, newValue, defaultCallback)
expect(target).toEqual(new Map([['foo', 'baz']]))
})

it('add new value', () => {
const target = new Map([['foo', 'bar']])
const newValue = 'baz'
const state = { newKey: 'bar', type: '', value: newValue }
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, 'bar', newValue, defaultCallback)
expect(target).toEqual(new Map([['foo', 'bar'], ['bar', 'baz']]))
})

it('remove value', () => {
const target = new Map([['foo', 'bar'], ['bar', 'baz']])
const state = { newKey: '', type: '', value: '', remove: true }
const path = 'foo'
const defaultCallback = stateEditor.createDefaultSetCallback(state)
stateEditor.set(target, path, '', defaultCallback)
expect(target).toEqual(new Map([['bar', 'baz']]))
})
})
})
9 changes: 6 additions & 3 deletions packages/devtools-kit/src/core/component/state/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ export class StateEditor {
const section = sections.shift()!
if (object instanceof Map)
object = object.get(section) as Recordable
else
object = object[section] as Recordable
if (object instanceof Set)
object = Array.from(object.values())[section] as Recordable
else object = object[section] as Recordable
if (this.refEditor.isRef(object))
object = this.refEditor.get(object)
}
Expand Down Expand Up @@ -79,7 +80,7 @@ export class StateEditor {
else if (toRaw(object) instanceof Map)
object.delete(field)
else if (toRaw(object) instanceof Set)
object.delete(value)
object.delete(Array.from(object.values())[field as number])
else Reflect.deleteProperty(object, field)
}
if (!state.remove) {
Expand All @@ -88,6 +89,8 @@ export class StateEditor {
this.refEditor.set(target, value)
else if (toRaw(object) instanceof Map)
object.set(state.newKey || field, value)
else if (toRaw(object) instanceof Set)
object.add(value)
else
object[state.newKey || field] = value
}
Expand Down

0 comments on commit 3addaad

Please sign in to comment.