Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 36x 19x 17x 70x 70x 19x 6x 13x 51x 18x 33x 3x 30x 30x 6x 14x 24x 39x 18x | /**
* Rejects NaN / Infinity and circular references in `tags`.
*
* `TagsPrimitive` is `number`, so `{ score: Number('oops') }` type-checks.
* JSON has no literal for those values. Each platform rewrites them
* differently (`null` on web, `0` on iOS via `NSNumber.intValue`, usually
* `null` on Android) and identification still succeeds. Throw instead of
* storing the wrong tag.
*
* A circular reference makes this walk recurse forever. Reject it with a
* clean error instead of letting it blow the call stack.
*
* `Date`, `Map`, and class instances are already a type error on `TagsValue`.
* This walk does not reject them. The RN bridge and JS agent do not agree on
* those values (a `Date` is an ISO string on web and `{}` on native), but we
* choose to ignore that.
*
* Size is a server `payload_too_large`.
* https://docs.fingerprint.com/docs/tagging-information
*/
export function validateTags(tags?: unknown): void {
if (tags === null || tags === undefined) {
return
}
walk(tags, 'tags', [])
}
function walk(value: unknown, path: string, ancestors: unknown[]): void {
Iif (value === null || value === undefined) {
return
}
if (typeof value === 'number') {
if (!Number.isFinite(value)) {
throw new TypeError(`${path} must be a finite number`)
}
return
}
if (typeof value !== 'object') {
return
}
if (ancestors.includes(value)) {
throw new TypeError(`${path} contains a circular reference`)
}
ancestors.push(value)
if (Array.isArray(value)) {
for (const [index, entry] of value.entries()) {
walk(entry, `${path}[${String(index)}]`, ancestors)
}
} else {
for (const [key, entry] of Object.entries(value)) {
walk(entry, `${path}['${key}']`, ancestors)
}
}
ancestors.pop()
}
|