Skip to content

Commit

Permalink
perf(path): improve path performance
Browse files Browse the repository at this point in the history
  • Loading branch information
janryWang committed May 18, 2021
1 parent c45c751 commit 4018d54
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 108 deletions.
14 changes: 7 additions & 7 deletions packages/core/src/shared/checkers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isFn, instOf } from '@formily/shared'
import { isFn } from '@formily/shared'
import {
Form,
Field,
Expand All @@ -16,27 +16,27 @@ import {
} from '../types'

export const isForm = (node: any): node is Form => {
return instOf(node, Form)
return node instanceof Form
}

export const isField = (node: any): node is Field => {
return instOf(node, Field)
return node instanceof Field
}

export const isGeneralField = (node: any): node is GeneralField => {
return instOf(node, Field) || instOf(node, VoidField)
return node instanceof Field || node instanceof VoidField
}

export const isArrayField = (node: any): node is ArrayField => {
return instOf(node, ArrayField)
return node instanceof ArrayField
}

export const isObjectField = (node: any): node is ObjectField => {
return instOf(node, ObjectField)
return node instanceof ObjectField
}

export const isVoidField = (node: any): node is VoidField => {
return instOf(node, VoidField)
return node instanceof VoidField
}

export const isFormState = (state: any): state is IFormState => {
Expand Down
112 changes: 13 additions & 99 deletions packages/path/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
import { Parser } from './parser'
import {
isStr,
isArr,
isFn,
isEqual,
isObj,
isNum,
isRegExp,
isPlainObj,
isAssignable,
} from './shared'
import { isStr, isArr, isFn, isEqual, isObj, isNum, isRegExp } from './shared'
import {
getDestructor,
getInByDestructor,
Expand All @@ -21,37 +11,7 @@ import { Segments, Node, Pattern, IRegistry, IAccessors } from './types'
import { LRUMap } from './lru'
import { Matcher } from './matcher'

const REGISTRY: IRegistry = {
accessors: {
get(source: any, key: number | string | symbol) {
if (isAssignable(source)) {
return Reflect.get(source, key)
}
},
set(source: any, key: number | string | symbol, value: any) {
if (isAssignable(source)) {
return Reflect.set(source, key, value)
}
},
has(source: any, key: number | string | symbol) {
if (isAssignable(source)) {
return Reflect.has(source, key)
}
return false
},
delete(source: any, key: number | string | symbol) {
if (isAssignable(source)) {
if (Array.isArray(source) && isNumberIndex(key)) {
source.splice(Number(key), 1)
return true
}
return Reflect.deleteProperty(source, key)
}
},
},
}

const pathCache = new LRUMap(1000)
const pathCache = new LRUMap(10000)

const isMatcher = Symbol('PATH_MATCHER')

Expand All @@ -60,14 +20,6 @@ const isValid = (val: any) => val !== undefined && val !== null
const isNumberIndex = (val: any) =>
isStr(val) ? /^\d+$/.test(val) : isNum(val)

const arrayExist = (obj: any, key: string | number) => {
if (Array.isArray(obj)) {
const index = Number(key)
if (index < 0 || index > obj.length - 1) return false
}
return true
}

const getIn = (segments: Segments, source: any) => {
for (let i = 0; i < segments.length; i++) {
const index = segments[i]
Expand All @@ -79,11 +31,7 @@ const getIn = (segments: Segments, source: any) => {
}
break
}
if (arrayExist(source, index)) {
source = REGISTRY.accessors.get(source, index)
} else {
return
}
source = source[index]
} else {
source = getInByDestructor(source, rules, { setIn, getIn })
break
Expand All @@ -101,35 +49,18 @@ const setIn = (segments: Segments, source: any, value: any) => {
if (isArr(source) && !isNumberIndex(index)) {
return
}
if (!arrayExist(source, index)) {
if (!isValid(source[index])) {
if (!isValid(value)) {
return
}
if (i < segments.length - 1) {
REGISTRY.accessors.set(
source,
index,
isNum(segments[i + 1]) ? [] : {}
)
}
} else if (!isValid(source[index])) {
if (!isValid(value)) {
return
}
if (i < segments.length - 1) {
REGISTRY.accessors.set(
source,
index,
isNum(segments[i + 1]) ? [] : {}
)
source[index] = isNum(segments[i + 1]) ? [] : {}
}
}
if (i === segments.length - 1) {
REGISTRY.accessors.set(source, index, value)
}
if (arrayExist(source, index)) {
source = REGISTRY.accessors.get(source, index)
source[index] = value
}
source = source[index]
} else {
setInByDestructor(source, rules, value, { setIn, getIn })
break
Expand All @@ -143,17 +74,12 @@ const deleteIn = (segments: Segments, source: any) => {
const rules = getDestructor(index as string)
if (!rules) {
if (i === segments.length - 1 && isValid(source)) {
REGISTRY.accessors.delete(source, index)
delete source[index]
return
}

if (!isValid(source)) return
if (arrayExist(source, index)) {
source = REGISTRY.accessors.get(source, index)
} else {
return
}

source = source[index]
if (!isObj(source)) {
return
}
Expand All @@ -168,6 +94,8 @@ const deleteIn = (segments: Segments, source: any) => {
}
}

const hasOwnProperty = Object.prototype.hasOwnProperty

const existIn = (segments: Segments, source: any, start: number | Path) => {
if (start instanceof Path) {
start = start.length
Expand All @@ -177,15 +105,11 @@ const existIn = (segments: Segments, source: any, start: number | Path) => {
const rules = getDestructor(index as string)
if (!rules) {
if (i === segments.length - 1) {
return REGISTRY.accessors.has(source, index)
return hasOwnProperty.call(source, index)
}

if (!isValid(source)) return false
if (arrayExist(source, index)) {
source = REGISTRY.accessors.get(source, index)
} else {
return false
}
source = source[index]

if (!isObj(source)) {
return false
Expand Down Expand Up @@ -617,16 +541,6 @@ export class Path {
const path = Path.parse(pattern)
return path.ensureIn(source, defaultValue)
}

static registerAccessors = (accessors: IAccessors) => {
if (isPlainObj(accessors)) {
for (const name in accessors) {
if (isFn(accessors[name])) {
REGISTRY.accessors[name] = accessors[name]
}
}
}
}
}

export { Pattern }
7 changes: 5 additions & 2 deletions packages/path/src/shared.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const isType = <T>(type: string) => (obj: unknown): obj is T =>
obj != null && Object.prototype.toString.call(obj) === `[object ${type}]`
const toString = Object.prototype.toString
const isType =
<T>(type: string) =>
(obj: unknown): obj is T =>
toString.call(obj) === `[object ${type}]`
export const isFn = isType<(...args: any[]) => any>('Function')
export const isArr = Array.isArray || isType<unknown[]>('Array')
export const isPlainObj = isType<object>('Object')
Expand Down

0 comments on commit 4018d54

Please sign in to comment.