'f'
mh-two-thousand-and-two
2024-04-12 26f2711ef9461961fb953e2b497bd314ef95e345
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import {
  isFn,
  hasOwn,
  toRawType,
  isPlainObject
} from 'uni-shared'
 
export default function validateParam (key, paramTypes, paramsData) {
  const paramOptions = paramTypes[key]
  const absent = !hasOwn(paramsData, key)
  let value = paramsData[key]
 
  const booleanIndex = getTypeIndex(Boolean, paramOptions.type)
  if (booleanIndex > -1) {
    if (absent && !hasOwn(paramOptions, 'default')) {
      value = false
    }
  }
  if (value === undefined) {
    if (hasOwn(paramOptions, 'default')) {
      const paramDefault = paramOptions.default
      value = isFn(paramDefault) ? paramDefault() : paramDefault
      paramsData[key] = value // 默认值
    }
  }
 
  return assertParam(paramOptions, key, value, absent, paramsData)
}
 
function assertParam (
  paramOptions,
  name,
  value,
  absent,
  paramsData
) {
  if (paramOptions.required && absent) {
    return `Missing required parameter \`${name}\``
  }
 
  if (value == null && !paramOptions.required) {
    const validator = paramOptions.validator
    if (validator) {
      return validator(value, paramsData)
    }
    return
  }
  let type = paramOptions.type
  let valid = !type || type === true
  const expectedTypes = []
  if (type) {
    if (!Array.isArray(type)) {
      type = [type]
    }
    for (let i = 0; i < type.length && !valid; i++) {
      const assertedType = assertType(value, type[i])
      expectedTypes.push(assertedType.expectedType || '')
      valid = assertedType.valid
    }
  }
 
  if (!valid) {
    return getInvalidTypeMessage(name, value, expectedTypes)
  }
 
  const validator = paramOptions.validator
  if (validator) {
    return validator(value, paramsData)
  }
}
 
const simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/
 
function assertType (value, type) {
  let valid
  const expectedType = getType(type)
  if (simpleCheckRE.test(expectedType)) {
    const t = typeof value
    valid = t === expectedType.toLowerCase()
    if (!valid && t === 'object') {
      valid = value instanceof type
    }
  } else if (value.byteLength >= 0) {
    valid = true
  } else if (expectedType === 'Object') {
    valid = isPlainObject(value)
  } else if (expectedType === 'Array') {
    valid = Array.isArray(value)
  } else {
    // TODO 页面传入的ArrayBuffer使用instanceof ArrayBuffer返回false,暂做此修改
    valid = value instanceof type || toRawType(value) === getType(type)
  }
  return {
    valid,
    expectedType
  }
}
 
function getType (fn) {
  const match = fn && fn.toString().match(/^\s*function (\w+)/)
  return match ? match[1] : ''
}
 
function isSameType (a, b) {
  return getType(a) === getType(b)
}
 
function getTypeIndex (type, expectedTypes) {
  if (!Array.isArray(expectedTypes)) {
    return isSameType(expectedTypes, type) ? 0 : -1
  }
  for (let i = 0, len = expectedTypes.length; i < len; i++) {
    if (isSameType(expectedTypes[i], type)) {
      return i
    }
  }
  return -1
}
 
function getInvalidTypeMessage (name, value, expectedTypes) {
  let message = `parameter \`${name}\`.` +
        ` Expected ${expectedTypes.join(', ')}`
  const expectedType = expectedTypes[0]
  const receivedType = toRawType(value)
  const expectedValue = styleValue(value, expectedType)
  const receivedValue = styleValue(value, receivedType)
  if (expectedTypes.length === 1 &&
        isExplicable(expectedType) &&
        !isBoolean(expectedType, receivedType)) {
    message += ` with value ${expectedValue}`
  }
  message += `, got ${receivedType} `
  if (isExplicable(receivedType)) {
    message += `with value ${receivedValue}.`
  }
  return message
}
 
function styleValue (value, type) {
  if (type === 'String') {
    return `"${value}"`
  } else if (type === 'Number') {
    return `${Number(value)}`
  } else {
    return `${value}`
  }
}
 
const explicitTypes = ['string', 'number', 'boolean']
 
function isExplicable (value) {
  return explicitTypes.some(elem => value.toLowerCase() === elem)
}
 
function isBoolean (...args) {
  return args.some(elem => elem.toLowerCase() === 'boolean')
}