utils.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. 'use strict';
  2. import bind from './helpers/bind.js';
  3. // utils is a library of generic helper functions non-specific to axios
  4. const { toString } = Object.prototype;
  5. const { getPrototypeOf } = Object;
  6. const { iterator, toStringTag } = Symbol;
  7. const kindOf = ((cache) => (thing) => {
  8. const str = toString.call(thing);
  9. return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
  10. })(Object.create(null));
  11. const kindOfTest = (type) => {
  12. type = type.toLowerCase();
  13. return (thing) => kindOf(thing) === type;
  14. };
  15. const typeOfTest = (type) => (thing) => typeof thing === type;
  16. /**
  17. * Determine if a value is a non-null object
  18. *
  19. * @param {Object} val The value to test
  20. *
  21. * @returns {boolean} True if value is an Array, otherwise false
  22. */
  23. const { isArray } = Array;
  24. /**
  25. * Determine if a value is undefined
  26. *
  27. * @param {*} val The value to test
  28. *
  29. * @returns {boolean} True if the value is undefined, otherwise false
  30. */
  31. const isUndefined = typeOfTest('undefined');
  32. /**
  33. * Determine if a value is a Buffer
  34. *
  35. * @param {*} val The value to test
  36. *
  37. * @returns {boolean} True if value is a Buffer, otherwise false
  38. */
  39. function isBuffer(val) {
  40. return (
  41. val !== null &&
  42. !isUndefined(val) &&
  43. val.constructor !== null &&
  44. !isUndefined(val.constructor) &&
  45. isFunction(val.constructor.isBuffer) &&
  46. val.constructor.isBuffer(val)
  47. );
  48. }
  49. /**
  50. * Determine if a value is an ArrayBuffer
  51. *
  52. * @param {*} val The value to test
  53. *
  54. * @returns {boolean} True if value is an ArrayBuffer, otherwise false
  55. */
  56. const isArrayBuffer = kindOfTest('ArrayBuffer');
  57. /**
  58. * Determine if a value is a view on an ArrayBuffer
  59. *
  60. * @param {*} val The value to test
  61. *
  62. * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
  63. */
  64. function isArrayBufferView(val) {
  65. let result;
  66. if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) {
  67. result = ArrayBuffer.isView(val);
  68. } else {
  69. result = val && val.buffer && isArrayBuffer(val.buffer);
  70. }
  71. return result;
  72. }
  73. /**
  74. * Determine if a value is a String
  75. *
  76. * @param {*} val The value to test
  77. *
  78. * @returns {boolean} True if value is a String, otherwise false
  79. */
  80. const isString = typeOfTest('string');
  81. /**
  82. * Determine if a value is a Function
  83. *
  84. * @param {*} val The value to test
  85. * @returns {boolean} True if value is a Function, otherwise false
  86. */
  87. const isFunction = typeOfTest('function');
  88. /**
  89. * Determine if a value is a Number
  90. *
  91. * @param {*} val The value to test
  92. *
  93. * @returns {boolean} True if value is a Number, otherwise false
  94. */
  95. const isNumber = typeOfTest('number');
  96. /**
  97. * Determine if a value is an Object
  98. *
  99. * @param {*} thing The value to test
  100. *
  101. * @returns {boolean} True if value is an Object, otherwise false
  102. */
  103. const isObject = (thing) => thing !== null && typeof thing === 'object';
  104. /**
  105. * Determine if a value is a Boolean
  106. *
  107. * @param {*} thing The value to test
  108. * @returns {boolean} True if value is a Boolean, otherwise false
  109. */
  110. const isBoolean = (thing) => thing === true || thing === false;
  111. /**
  112. * Determine if a value is a plain Object
  113. *
  114. * @param {*} val The value to test
  115. *
  116. * @returns {boolean} True if value is a plain Object, otherwise false
  117. */
  118. const isPlainObject = (val) => {
  119. if (kindOf(val) !== 'object') {
  120. return false;
  121. }
  122. const prototype = getPrototypeOf(val);
  123. return (
  124. (prototype === null ||
  125. prototype === Object.prototype ||
  126. Object.getPrototypeOf(prototype) === null) &&
  127. !(toStringTag in val) &&
  128. !(iterator in val)
  129. );
  130. };
  131. /**
  132. * Determine if a value is an empty object (safely handles Buffers)
  133. *
  134. * @param {*} val The value to test
  135. *
  136. * @returns {boolean} True if value is an empty object, otherwise false
  137. */
  138. const isEmptyObject = (val) => {
  139. // Early return for non-objects or Buffers to prevent RangeError
  140. if (!isObject(val) || isBuffer(val)) {
  141. return false;
  142. }
  143. try {
  144. return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype;
  145. } catch (e) {
  146. // Fallback for any other objects that might cause RangeError with Object.keys()
  147. return false;
  148. }
  149. };
  150. /**
  151. * Determine if a value is a Date
  152. *
  153. * @param {*} val The value to test
  154. *
  155. * @returns {boolean} True if value is a Date, otherwise false
  156. */
  157. const isDate = kindOfTest('Date');
  158. /**
  159. * Determine if a value is a File
  160. *
  161. * @param {*} val The value to test
  162. *
  163. * @returns {boolean} True if value is a File, otherwise false
  164. */
  165. const isFile = kindOfTest('File');
  166. /**
  167. * Determine if a value is a React Native Blob
  168. * React Native "blob": an object with a `uri` attribute. Optionally, it can
  169. * also have a `name` and `type` attribute to specify filename and content type
  170. *
  171. * @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71
  172. *
  173. * @param {*} value The value to test
  174. *
  175. * @returns {boolean} True if value is a React Native Blob, otherwise false
  176. */
  177. const isReactNativeBlob = (value) => {
  178. return !!(value && typeof value.uri !== 'undefined');
  179. };
  180. /**
  181. * Determine if environment is React Native
  182. * ReactNative `FormData` has a non-standard `getParts()` method
  183. *
  184. * @param {*} formData The formData to test
  185. *
  186. * @returns {boolean} True if environment is React Native, otherwise false
  187. */
  188. const isReactNative = (formData) => formData && typeof formData.getParts !== 'undefined';
  189. /**
  190. * Determine if a value is a Blob
  191. *
  192. * @param {*} val The value to test
  193. *
  194. * @returns {boolean} True if value is a Blob, otherwise false
  195. */
  196. const isBlob = kindOfTest('Blob');
  197. /**
  198. * Determine if a value is a FileList
  199. *
  200. * @param {*} val The value to test
  201. *
  202. * @returns {boolean} True if value is a FileList, otherwise false
  203. */
  204. const isFileList = kindOfTest('FileList');
  205. /**
  206. * Determine if a value is a Stream
  207. *
  208. * @param {*} val The value to test
  209. *
  210. * @returns {boolean} True if value is a Stream, otherwise false
  211. */
  212. const isStream = (val) => isObject(val) && isFunction(val.pipe);
  213. /**
  214. * Determine if a value is a FormData
  215. *
  216. * @param {*} thing The value to test
  217. *
  218. * @returns {boolean} True if value is an FormData, otherwise false
  219. */
  220. function getGlobal() {
  221. if (typeof globalThis !== 'undefined') return globalThis;
  222. if (typeof self !== 'undefined') return self;
  223. if (typeof window !== 'undefined') return window;
  224. if (typeof global !== 'undefined') return global;
  225. return {};
  226. }
  227. const G = getGlobal();
  228. const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined;
  229. const isFormData = (thing) => {
  230. if (!thing) return false;
  231. if (FormDataCtor && thing instanceof FormDataCtor) return true;
  232. // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData.
  233. const proto = getPrototypeOf(thing);
  234. if (!proto || proto === Object.prototype) return false;
  235. if (!isFunction(thing.append)) return false;
  236. const kind = kindOf(thing);
  237. return (
  238. kind === 'formdata' ||
  239. // detect form-data instance
  240. (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
  241. );
  242. };
  243. /**
  244. * Determine if a value is a URLSearchParams object
  245. *
  246. * @param {*} val The value to test
  247. *
  248. * @returns {boolean} True if value is a URLSearchParams object, otherwise false
  249. */
  250. const isURLSearchParams = kindOfTest('URLSearchParams');
  251. const [isReadableStream, isRequest, isResponse, isHeaders] = [
  252. 'ReadableStream',
  253. 'Request',
  254. 'Response',
  255. 'Headers',
  256. ].map(kindOfTest);
  257. /**
  258. * Trim excess whitespace off the beginning and end of a string
  259. *
  260. * @param {String} str The String to trim
  261. *
  262. * @returns {String} The String freed of excess whitespace
  263. */
  264. const trim = (str) => {
  265. return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  266. };
  267. /**
  268. * Iterate over an Array or an Object invoking a function for each item.
  269. *
  270. * If `obj` is an Array callback will be called passing
  271. * the value, index, and complete array for each item.
  272. *
  273. * If 'obj' is an Object callback will be called passing
  274. * the value, key, and complete object for each property.
  275. *
  276. * @param {Object|Array<unknown>} obj The object to iterate
  277. * @param {Function} fn The callback to invoke for each item
  278. *
  279. * @param {Object} [options]
  280. * @param {Boolean} [options.allOwnKeys = false]
  281. * @returns {any}
  282. */
  283. function forEach(obj, fn, { allOwnKeys = false } = {}) {
  284. // Don't bother if no value provided
  285. if (obj === null || typeof obj === 'undefined') {
  286. return;
  287. }
  288. let i;
  289. let l;
  290. // Force an array if not already something iterable
  291. if (typeof obj !== 'object') {
  292. /*eslint no-param-reassign:0*/
  293. obj = [obj];
  294. }
  295. if (isArray(obj)) {
  296. // Iterate over array values
  297. for (i = 0, l = obj.length; i < l; i++) {
  298. fn.call(null, obj[i], i, obj);
  299. }
  300. } else {
  301. // Buffer check
  302. if (isBuffer(obj)) {
  303. return;
  304. }
  305. // Iterate over object keys
  306. const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
  307. const len = keys.length;
  308. let key;
  309. for (i = 0; i < len; i++) {
  310. key = keys[i];
  311. fn.call(null, obj[key], key, obj);
  312. }
  313. }
  314. }
  315. /**
  316. * Finds a key in an object, case-insensitive, returning the actual key name.
  317. * Returns null if the object is a Buffer or if no match is found.
  318. *
  319. * @param {Object} obj - The object to search.
  320. * @param {string} key - The key to find (case-insensitive).
  321. * @returns {?string} The actual key name if found, otherwise null.
  322. */
  323. function findKey(obj, key) {
  324. if (isBuffer(obj)) {
  325. return null;
  326. }
  327. key = key.toLowerCase();
  328. const keys = Object.keys(obj);
  329. let i = keys.length;
  330. let _key;
  331. while (i-- > 0) {
  332. _key = keys[i];
  333. if (key === _key.toLowerCase()) {
  334. return _key;
  335. }
  336. }
  337. return null;
  338. }
  339. const _global = (() => {
  340. /*eslint no-undef:0*/
  341. if (typeof globalThis !== 'undefined') return globalThis;
  342. return typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : global;
  343. })();
  344. const isContextDefined = (context) => !isUndefined(context) && context !== _global;
  345. /**
  346. * Accepts varargs expecting each argument to be an object, then
  347. * immutably merges the properties of each object and returns result.
  348. *
  349. * When multiple objects contain the same key the later object in
  350. * the arguments list will take precedence.
  351. *
  352. * Example:
  353. *
  354. * ```js
  355. * const result = merge({foo: 123}, {foo: 456});
  356. * console.log(result.foo); // outputs 456
  357. * ```
  358. *
  359. * @param {Object} obj1 Object to merge
  360. *
  361. * @returns {Object} Result of all merge properties
  362. */
  363. function merge(...objs) {
  364. const { caseless, skipUndefined } = (isContextDefined(this) && this) || {};
  365. const result = {};
  366. const assignValue = (val, key) => {
  367. // Skip dangerous property names to prevent prototype pollution
  368. if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
  369. return;
  370. }
  371. const targetKey = (caseless && findKey(result, key)) || key;
  372. // Read via own-prop only — a bare `result[targetKey]` walks the prototype
  373. // chain, so a polluted Object.prototype value could surface here and get
  374. // copied into the merged result.
  375. const existing = hasOwnProperty(result, targetKey) ? result[targetKey] : undefined;
  376. if (isPlainObject(existing) && isPlainObject(val)) {
  377. result[targetKey] = merge(existing, val);
  378. } else if (isPlainObject(val)) {
  379. result[targetKey] = merge({}, val);
  380. } else if (isArray(val)) {
  381. result[targetKey] = val.slice();
  382. } else if (!skipUndefined || !isUndefined(val)) {
  383. result[targetKey] = val;
  384. }
  385. };
  386. for (let i = 0, l = objs.length; i < l; i++) {
  387. objs[i] && forEach(objs[i], assignValue);
  388. }
  389. return result;
  390. }
  391. /**
  392. * Extends object a by mutably adding to it the properties of object b.
  393. *
  394. * @param {Object} a The object to be extended
  395. * @param {Object} b The object to copy properties from
  396. * @param {Object} thisArg The object to bind function to
  397. *
  398. * @param {Object} [options]
  399. * @param {Boolean} [options.allOwnKeys]
  400. * @returns {Object} The resulting value of object a
  401. */
  402. const extend = (a, b, thisArg, { allOwnKeys } = {}) => {
  403. forEach(
  404. b,
  405. (val, key) => {
  406. if (thisArg && isFunction(val)) {
  407. Object.defineProperty(a, key, {
  408. // Null-proto descriptor so a polluted Object.prototype.get cannot
  409. // hijack defineProperty's accessor-vs-data resolution.
  410. __proto__: null,
  411. value: bind(val, thisArg),
  412. writable: true,
  413. enumerable: true,
  414. configurable: true,
  415. });
  416. } else {
  417. Object.defineProperty(a, key, {
  418. __proto__: null,
  419. value: val,
  420. writable: true,
  421. enumerable: true,
  422. configurable: true,
  423. });
  424. }
  425. },
  426. { allOwnKeys }
  427. );
  428. return a;
  429. };
  430. /**
  431. * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
  432. *
  433. * @param {string} content with BOM
  434. *
  435. * @returns {string} content value without BOM
  436. */
  437. const stripBOM = (content) => {
  438. if (content.charCodeAt(0) === 0xfeff) {
  439. content = content.slice(1);
  440. }
  441. return content;
  442. };
  443. /**
  444. * Inherit the prototype methods from one constructor into another
  445. * @param {function} constructor
  446. * @param {function} superConstructor
  447. * @param {object} [props]
  448. * @param {object} [descriptors]
  449. *
  450. * @returns {void}
  451. */
  452. const inherits = (constructor, superConstructor, props, descriptors) => {
  453. constructor.prototype = Object.create(superConstructor.prototype, descriptors);
  454. Object.defineProperty(constructor.prototype, 'constructor', {
  455. __proto__: null,
  456. value: constructor,
  457. writable: true,
  458. enumerable: false,
  459. configurable: true,
  460. });
  461. Object.defineProperty(constructor, 'super', {
  462. __proto__: null,
  463. value: superConstructor.prototype,
  464. });
  465. props && Object.assign(constructor.prototype, props);
  466. };
  467. /**
  468. * Resolve object with deep prototype chain to a flat object
  469. * @param {Object} sourceObj source object
  470. * @param {Object} [destObj]
  471. * @param {Function|Boolean} [filter]
  472. * @param {Function} [propFilter]
  473. *
  474. * @returns {Object}
  475. */
  476. const toFlatObject = (sourceObj, destObj, filter, propFilter) => {
  477. let props;
  478. let i;
  479. let prop;
  480. const merged = {};
  481. destObj = destObj || {};
  482. // eslint-disable-next-line no-eq-null,eqeqeq
  483. if (sourceObj == null) return destObj;
  484. do {
  485. props = Object.getOwnPropertyNames(sourceObj);
  486. i = props.length;
  487. while (i-- > 0) {
  488. prop = props[i];
  489. if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) {
  490. destObj[prop] = sourceObj[prop];
  491. merged[prop] = true;
  492. }
  493. }
  494. sourceObj = filter !== false && getPrototypeOf(sourceObj);
  495. } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
  496. return destObj;
  497. };
  498. /**
  499. * Determines whether a string ends with the characters of a specified string
  500. *
  501. * @param {String} str
  502. * @param {String} searchString
  503. * @param {Number} [position= 0]
  504. *
  505. * @returns {boolean}
  506. */
  507. const endsWith = (str, searchString, position) => {
  508. str = String(str);
  509. if (position === undefined || position > str.length) {
  510. position = str.length;
  511. }
  512. position -= searchString.length;
  513. const lastIndex = str.indexOf(searchString, position);
  514. return lastIndex !== -1 && lastIndex === position;
  515. };
  516. /**
  517. * Returns new array from array like object or null if failed
  518. *
  519. * @param {*} [thing]
  520. *
  521. * @returns {?Array}
  522. */
  523. const toArray = (thing) => {
  524. if (!thing) return null;
  525. if (isArray(thing)) return thing;
  526. let i = thing.length;
  527. if (!isNumber(i)) return null;
  528. const arr = new Array(i);
  529. while (i-- > 0) {
  530. arr[i] = thing[i];
  531. }
  532. return arr;
  533. };
  534. /**
  535. * Checking if the Uint8Array exists and if it does, it returns a function that checks if the
  536. * thing passed in is an instance of Uint8Array
  537. *
  538. * @param {TypedArray}
  539. *
  540. * @returns {Array}
  541. */
  542. // eslint-disable-next-line func-names
  543. const isTypedArray = ((TypedArray) => {
  544. // eslint-disable-next-line func-names
  545. return (thing) => {
  546. return TypedArray && thing instanceof TypedArray;
  547. };
  548. })(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array));
  549. /**
  550. * For each entry in the object, call the function with the key and value.
  551. *
  552. * @param {Object<any, any>} obj - The object to iterate over.
  553. * @param {Function} fn - The function to call for each entry.
  554. *
  555. * @returns {void}
  556. */
  557. const forEachEntry = (obj, fn) => {
  558. const generator = obj && obj[iterator];
  559. const _iterator = generator.call(obj);
  560. let result;
  561. while ((result = _iterator.next()) && !result.done) {
  562. const pair = result.value;
  563. fn.call(obj, pair[0], pair[1]);
  564. }
  565. };
  566. /**
  567. * It takes a regular expression and a string, and returns an array of all the matches
  568. *
  569. * @param {string} regExp - The regular expression to match against.
  570. * @param {string} str - The string to search.
  571. *
  572. * @returns {Array<boolean>}
  573. */
  574. const matchAll = (regExp, str) => {
  575. let matches;
  576. const arr = [];
  577. while ((matches = regExp.exec(str)) !== null) {
  578. arr.push(matches);
  579. }
  580. return arr;
  581. };
  582. /* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */
  583. const isHTMLForm = kindOfTest('HTMLFormElement');
  584. const toCamelCase = (str) => {
  585. return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(m, p1, p2) {
  586. return p1.toUpperCase() + p2;
  587. });
  588. };
  589. /* Creating a function that will check if an object has a property. */
  590. const hasOwnProperty = (
  591. ({ hasOwnProperty }) =>
  592. (obj, prop) =>
  593. hasOwnProperty.call(obj, prop)
  594. )(Object.prototype);
  595. /**
  596. * Determine if a value is a RegExp object
  597. *
  598. * @param {*} val The value to test
  599. *
  600. * @returns {boolean} True if value is a RegExp object, otherwise false
  601. */
  602. const isRegExp = kindOfTest('RegExp');
  603. const reduceDescriptors = (obj, reducer) => {
  604. const descriptors = Object.getOwnPropertyDescriptors(obj);
  605. const reducedDescriptors = {};
  606. forEach(descriptors, (descriptor, name) => {
  607. let ret;
  608. if ((ret = reducer(descriptor, name, obj)) !== false) {
  609. reducedDescriptors[name] = ret || descriptor;
  610. }
  611. });
  612. Object.defineProperties(obj, reducedDescriptors);
  613. };
  614. /**
  615. * Makes all methods read-only
  616. * @param {Object} obj
  617. */
  618. const freezeMethods = (obj) => {
  619. reduceDescriptors(obj, (descriptor, name) => {
  620. // skip restricted props in strict mode
  621. if (isFunction(obj) && ['arguments', 'caller', 'callee'].includes(name)) {
  622. return false;
  623. }
  624. const value = obj[name];
  625. if (!isFunction(value)) return;
  626. descriptor.enumerable = false;
  627. if ('writable' in descriptor) {
  628. descriptor.writable = false;
  629. return;
  630. }
  631. if (!descriptor.set) {
  632. descriptor.set = () => {
  633. throw Error("Can not rewrite read-only method '" + name + "'");
  634. };
  635. }
  636. });
  637. };
  638. /**
  639. * Converts an array or a delimited string into an object set with values as keys and true as values.
  640. * Useful for fast membership checks.
  641. *
  642. * @param {Array|string} arrayOrString - The array or string to convert.
  643. * @param {string} delimiter - The delimiter to use if input is a string.
  644. * @returns {Object} An object with keys from the array or string, values set to true.
  645. */
  646. const toObjectSet = (arrayOrString, delimiter) => {
  647. const obj = {};
  648. const define = (arr) => {
  649. arr.forEach((value) => {
  650. obj[value] = true;
  651. });
  652. };
  653. isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));
  654. return obj;
  655. };
  656. const noop = () => {};
  657. const toFiniteNumber = (value, defaultValue) => {
  658. return value != null && Number.isFinite((value = +value)) ? value : defaultValue;
  659. };
  660. /**
  661. * If the thing is a FormData object, return true, otherwise return false.
  662. *
  663. * @param {unknown} thing - The thing to check.
  664. *
  665. * @returns {boolean}
  666. */
  667. function isSpecCompliantForm(thing) {
  668. return !!(
  669. thing &&
  670. isFunction(thing.append) &&
  671. thing[toStringTag] === 'FormData' &&
  672. thing[iterator]
  673. );
  674. }
  675. /**
  676. * Recursively converts an object to a JSON-compatible object, handling circular references and Buffers.
  677. *
  678. * @param {Object} obj - The object to convert.
  679. * @returns {Object} The JSON-compatible object.
  680. */
  681. const toJSONObject = (obj) => {
  682. const stack = new Array(10);
  683. const visit = (source, i) => {
  684. if (isObject(source)) {
  685. if (stack.indexOf(source) >= 0) {
  686. return;
  687. }
  688. //Buffer check
  689. if (isBuffer(source)) {
  690. return source;
  691. }
  692. if (!('toJSON' in source)) {
  693. stack[i] = source;
  694. const target = isArray(source) ? [] : {};
  695. forEach(source, (value, key) => {
  696. const reducedValue = visit(value, i + 1);
  697. !isUndefined(reducedValue) && (target[key] = reducedValue);
  698. });
  699. stack[i] = undefined;
  700. return target;
  701. }
  702. }
  703. return source;
  704. };
  705. return visit(obj, 0);
  706. };
  707. /**
  708. * Determines if a value is an async function.
  709. *
  710. * @param {*} thing - The value to test.
  711. * @returns {boolean} True if value is an async function, otherwise false.
  712. */
  713. const isAsyncFn = kindOfTest('AsyncFunction');
  714. /**
  715. * Determines if a value is thenable (has then and catch methods).
  716. *
  717. * @param {*} thing - The value to test.
  718. * @returns {boolean} True if value is thenable, otherwise false.
  719. */
  720. const isThenable = (thing) =>
  721. thing &&
  722. (isObject(thing) || isFunction(thing)) &&
  723. isFunction(thing.then) &&
  724. isFunction(thing.catch);
  725. // original code
  726. // https://github.com/DigitalBrainJS/AxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34
  727. /**
  728. * Provides a cross-platform setImmediate implementation.
  729. * Uses native setImmediate if available, otherwise falls back to postMessage or setTimeout.
  730. *
  731. * @param {boolean} setImmediateSupported - Whether setImmediate is supported.
  732. * @param {boolean} postMessageSupported - Whether postMessage is supported.
  733. * @returns {Function} A function to schedule a callback asynchronously.
  734. */
  735. const _setImmediate = ((setImmediateSupported, postMessageSupported) => {
  736. if (setImmediateSupported) {
  737. return setImmediate;
  738. }
  739. return postMessageSupported
  740. ? ((token, callbacks) => {
  741. _global.addEventListener(
  742. 'message',
  743. ({ source, data }) => {
  744. if (source === _global && data === token) {
  745. callbacks.length && callbacks.shift()();
  746. }
  747. },
  748. false
  749. );
  750. return (cb) => {
  751. callbacks.push(cb);
  752. _global.postMessage(token, '*');
  753. };
  754. })(`axios@${Math.random()}`, [])
  755. : (cb) => setTimeout(cb);
  756. })(typeof setImmediate === 'function', isFunction(_global.postMessage));
  757. /**
  758. * Schedules a microtask or asynchronous callback as soon as possible.
  759. * Uses queueMicrotask if available, otherwise falls back to process.nextTick or _setImmediate.
  760. *
  761. * @type {Function}
  762. */
  763. const asap =
  764. typeof queueMicrotask !== 'undefined'
  765. ? queueMicrotask.bind(_global)
  766. : (typeof process !== 'undefined' && process.nextTick) || _setImmediate;
  767. // *********************
  768. const isIterable = (thing) => thing != null && isFunction(thing[iterator]);
  769. export default {
  770. isArray,
  771. isArrayBuffer,
  772. isBuffer,
  773. isFormData,
  774. isArrayBufferView,
  775. isString,
  776. isNumber,
  777. isBoolean,
  778. isObject,
  779. isPlainObject,
  780. isEmptyObject,
  781. isReadableStream,
  782. isRequest,
  783. isResponse,
  784. isHeaders,
  785. isUndefined,
  786. isDate,
  787. isFile,
  788. isReactNativeBlob,
  789. isReactNative,
  790. isBlob,
  791. isRegExp,
  792. isFunction,
  793. isStream,
  794. isURLSearchParams,
  795. isTypedArray,
  796. isFileList,
  797. forEach,
  798. merge,
  799. extend,
  800. trim,
  801. stripBOM,
  802. inherits,
  803. toFlatObject,
  804. kindOf,
  805. kindOfTest,
  806. endsWith,
  807. toArray,
  808. forEachEntry,
  809. matchAll,
  810. isHTMLForm,
  811. hasOwnProperty,
  812. hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection
  813. reduceDescriptors,
  814. freezeMethods,
  815. toObjectSet,
  816. toCamelCase,
  817. noop,
  818. toFiniteNumber,
  819. findKey,
  820. global: _global,
  821. isContextDefined,
  822. isSpecCompliantForm,
  823. toJSONObject,
  824. isAsyncFn,
  825. isThenable,
  826. setImmediate: _setImmediate,
  827. asap,
  828. isIterable,
  829. };