forked from vitest-dev/vitest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
base.ts
101 lines (84 loc) · 2.5 KB
/
base.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import type { Arrayable, DeepMerge, Nullable } from '../types'
export function notNullish<T>(v: T | null | undefined): v is NonNullable<T> {
return v != null
}
export function slash(str: string) {
return str.replace(/\\/g, '/')
}
export function mergeSlashes(str: string) {
return str.replace(/\/\//g, '/')
}
export const noop = () => { }
export function clone<T>(val: T): T {
let k: any, out: any, tmp: any
if (Array.isArray(val)) {
out = Array(k = val.length)
while (k--)
// eslint-disable-next-line no-cond-assign
out[k] = (tmp = val[k]) && typeof tmp === 'object' ? clone(tmp) : tmp
return out as any
}
if (Object.prototype.toString.call(val) === '[object Object]') {
out = {} // null
for (k in val) {
if (k === '__proto__') {
Object.defineProperty(out, k, {
value: clone((val as any)[k]),
configurable: true,
enumerable: true,
writable: true,
})
}
else {
// eslint-disable-next-line no-cond-assign
out[k] = (tmp = (val as any)[k]) && typeof tmp === 'object' ? clone(tmp) : tmp
}
}
return out
}
return val
}
/**
* Convert `Arrayable<T>` to `Array<T>`
*
* @category Array
*/
export function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T> {
array = array || []
if (Array.isArray(array))
return array
return [array]
}
export const toString = (v: any) => Object.prototype.toString.call(v)
export const isPlainObject = (val: any): val is object => toString(val) === '[object Object]'
export function isObject(item: unknown): boolean {
return item != null && typeof item === 'object' && !Array.isArray(item)
}
/**
* Deep merge :P
*
* Will merge objects only if they are plain
*/
export function deepMerge<T extends object = object, S extends object = T>(target: T, ...sources: S[]): DeepMerge<T, S> {
if (!sources.length)
return target as any
const source = sources.shift()
if (source === undefined)
return target as any
if (isMergableObject(target) && isMergableObject(source)) {
(Object.keys(source) as (keyof S & keyof T)[]).forEach((key) => {
if (isMergableObject(source[key])) {
if (!target[key])
target[key] = {} as any
deepMerge(target[key] as any, source[key] as any)
}
else {
target[key] = source[key] as any
}
})
}
return deepMerge(target, ...sources)
}
function isMergableObject(item: any): item is Object {
return isPlainObject(item) && !Array.isArray(item)
}