axios
Version:
Promise based HTTP client for the browser and node.js
50 lines (45 loc) • 1.62 kB
JavaScript
;
import utils from '../utils.js';
import AxiosError from './AxiosError.js';
export default function assertParamsAcyclic(params) {
const pending = [{ value: params }];
const active = new WeakSet();
const visited = new WeakSet();
while (pending.length) {
const { value, done } = pending.pop();
if (!utils.isPlainObject(value) && !utils.isArray(value)) continue;
if (done) {
active.delete(value);
continue;
}
if (active.has(value)) {
throw new AxiosError(
'Circular reference detected in params',
AxiosError.ERR_BAD_OPTION_VALUE
);
}
if (visited.has(value)) continue;
visited.add(value);
active.add(value);
pending.push({ value, done: true });
const keys = Object.keys(value);
if (Object.getOwnPropertySymbols && Object.getOwnPropertyDescriptor) {
Object.getOwnPropertySymbols(value).forEach((key) => {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
if (descriptor && descriptor.enumerable) keys.push(key);
});
}
// Shallow array elements retain fields filtered during plain-object merges.
// Inspect reserved data properties without evaluating their accessors.
keys.forEach((key) => {
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
if (descriptor && utils.hasOwnProp(descriptor, 'value')) {
pending.push({ value: descriptor.value });
}
} else {
pending.push({ value: value[key] });
}
});
}
}