codekingpro/portable-devtools
115k
1'use strict';2 3import bind from './helpers/bind.js';4 5// utils is a library of generic helper functions non-specific to axios6 7const {toString} = Object.prototype;8const {getPrototypeOf} = Object;9 10const kindOf = (cache => thing => {11 const str = toString.call(thing);12 return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());13})(Object.create(null));14 15const kindOfTest = (type) => {16 type = type.toLowerCase();17 return (thing) => kindOf(thing) === type18}19 20const typeOfTest = type => thing => typeof thing === type;21 22/**23 * Determine if a value is an Array24 *25 * @param {Object} val The value to test26 *27 * @returns {boolean} True if value is an Array, otherwise false28 */29const {isArray} = Array;30 31/**32 * Determine if a value is undefined33 *34 * @param {*} val The value to test35 *36 * @returns {boolean} True if the value is undefined, otherwise false37 */38const isUndefined = typeOfTest('undefined');39 40/**41 * Determine if a value is a Buffer42 *43 * @param {*} val The value to test44 *45 * @returns {boolean} True if value is a Buffer, otherwise false46 */47function isBuffer(val) {48 return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)49 && isFunction(val.constructor.isBuffer) && val.constructor.isBuffer(val);50}51 52/**53 * Determine if a value is an ArrayBuffer54 *55 * @param {*} val The value to test56 *57 * @returns {boolean} True if value is an ArrayBuffer, otherwise false58 */59const isArrayBuffer = kindOfTest('ArrayBuffer');60 61 62/**63 * Determine if a value is a view on an ArrayBuffer64 *65 * @param {*} val The value to test66 *67 * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false68 */69function isArrayBufferView(val) {70 let result;71 if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {72 result = ArrayBuffer.isView(val);73 } else {74 result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));75 }76 return result;77}78 79/**80 * Determine if a value is a String81 *82 * @param {*} val The value to test83 *84 * @returns {boolean} True if value is a String, otherwise false85 */86const isString = typeOfTest('string');87 88/**89 * Determine if a value is a Function90 *91 * @param {*} val The value to test92 * @returns {boolean} True if value is a Function, otherwise false93 */94const isFunction = typeOfTest('function');95 96/**97 * Determine if a value is a Number98 *99 * @param {*} val The value to test100 *101 * @returns {boolean} True if value is a Number, otherwise false102 */103const isNumber = typeOfTest('number');104 105/**106 * Determine if a value is an Object107 *108 * @param {*} thing The value to test109 *110 * @returns {boolean} True if value is an Object, otherwise false111 */112const isObject = (thing) => thing !== null && typeof thing === 'object';113 114/**115 * Determine if a value is a Boolean116 *117 * @param {*} thing The value to test118 * @returns {boolean} True if value is a Boolean, otherwise false119 */120const isBoolean = thing => thing === true || thing === false;121 122/**123 * Determine if a value is a plain Object124 *125 * @param {*} val The value to test126 *127 * @returns {boolean} True if value is a plain Object, otherwise false128 */129const isPlainObject = (val) => {130 if (kindOf(val) !== 'object') {131 return false;132 }133 134 const prototype = getPrototypeOf(val);135 return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in val) && !(Symbol.iterator in val);136}137 138/**139 * Determine if a value is a Date140 *141 * @param {*} val The value to test142 *143 * @returns {boolean} True if value is a Date, otherwise false144 */145const isDate = kindOfTest('Date');146 147/**148 * Determine if a value is a File149 *150 * @param {*} val The value to test151 *152 * @returns {boolean} True if value is a File, otherwise false153 */154const isFile = kindOfTest('File');155 156/**157 * Determine if a value is a Blob158 *159 * @param {*} val The value to test160 *161 * @returns {boolean} True if value is a Blob, otherwise false162 */163const isBlob = kindOfTest('Blob');164 165/**166 * Determine if a value is a FileList167 *168 * @param {*} val The value to test169 *170 * @returns {boolean} True if value is a File, otherwise false171 */172const isFileList = kindOfTest('FileList');173 174/**175 * Determine if a value is a Stream176 *177 * @param {*} val The value to test178 *179 * @returns {boolean} True if value is a Stream, otherwise false180 */181const isStream = (val) => isObject(val) && isFunction(val.pipe);182 183/**184 * Determine if a value is a FormData185 *186 * @param {*} thing The value to test187 *188 * @returns {boolean} True if value is an FormData, otherwise false189 */190const isFormData = (thing) => {191 let kind;192 return thing && (193 (typeof FormData === 'function' && thing instanceof FormData) || (194 isFunction(thing.append) && (195 (kind = kindOf(thing)) === 'formdata' ||196 // detect form-data instance197 (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')198 )199 )200 )201}202 203/**204 * Determine if a value is a URLSearchParams object205 *206 * @param {*} val The value to test207 *208 * @returns {boolean} True if value is a URLSearchParams object, otherwise false209 */210const isURLSearchParams = kindOfTest('URLSearchParams');211 212/**213 * Trim excess whitespace off the beginning and end of a string214 *215 * @param {String} str The String to trim216 *217 * @returns {String} The String freed of excess whitespace218 */219const trim = (str) => str.trim ?220 str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');221 222/**223 * Iterate over an Array or an Object invoking a function for each item.224 *225 * If `obj` is an Array callback will be called passing226 * the value, index, and complete array for each item.227 *228 * If 'obj' is an Object callback will be called passing229 * the value, key, and complete object for each property.230 *231 * @param {Object|Array} obj The object to iterate232 * @param {Function} fn The callback to invoke for each item233 *234 * @param {Boolean} [allOwnKeys = false]235 * @returns {any}236 */237function forEach(obj, fn, {allOwnKeys = false} = {}) {238 // Don't bother if no value provided239 if (obj === null || typeof obj === 'undefined') {240 return;241 }242 243 let i;244 let l;245 246 // Force an array if not already something iterable247 if (typeof obj !== 'object') {248 /*eslint no-param-reassign:0*/249 obj = [obj];250 }251 252 if (isArray(obj)) {253 // Iterate over array values254 for (i = 0, l = obj.length; i < l; i++) {255 fn.call(null, obj[i], i, obj);256 }257 } else {258 // Iterate over object keys259 const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);260 const len = keys.length;261 let key;262 263 for (i = 0; i < len; i++) {264 key = keys[i];265 fn.call(null, obj[key], key, obj);266 }267 }268}269 270function findKey(obj, key) {271 key = key.toLowerCase();272 const keys = Object.keys(obj);273 let i = keys.length;274 let _key;275 while (i-- > 0) {276 _key = keys[i];277 if (key === _key.toLowerCase()) {278 return _key;279 }280 }281 return null;282}283 284const _global = (() => {285 /*eslint no-undef:0*/286 if (typeof globalThis !== "undefined") return globalThis;287 return typeof self !== "undefined" ? self : (typeof window !== 'undefined' ? window : global)288})();289 290const isContextDefined = (context) => !isUndefined(context) && context !== _global;291 292/**293 * Accepts varargs expecting each argument to be an object, then294 * immutably merges the properties of each object and returns result.295 *296 * When multiple objects contain the same key the later object in297 * the arguments list will take precedence.298 *299 * Example:300 *301 * ```js302 * var result = merge({foo: 123}, {foo: 456});303 * console.log(result.foo); // outputs 456304 * ```305 *306 * @param {Object} obj1 Object to merge307 *308 * @returns {Object} Result of all merge properties309 */310function merge(/* obj1, obj2, obj3, ... */) {311 const {caseless} = isContextDefined(this) && this || {};312 const result = {};313 const assignValue = (val, key) => {314 const targetKey = caseless && findKey(result, key) || key;315 if (isPlainObject(result[targetKey]) && isPlainObject(val)) {316 result[targetKey] = merge(result[targetKey], val);317 } else if (isPlainObject(val)) {318 result[targetKey] = merge({}, val);319 } else if (isArray(val)) {320 result[targetKey] = val.slice();321 } else {322 result[targetKey] = val;323 }324 }325 326 for (let i = 0, l = arguments.length; i < l; i++) {327 arguments[i] && forEach(arguments[i], assignValue);328 }329 return result;330}331 332/**333 * Extends object a by mutably adding to it the properties of object b.334 *335 * @param {Object} a The object to be extended336 * @param {Object} b The object to copy properties from337 * @param {Object} thisArg The object to bind function to338 *339 * @param {Boolean} [allOwnKeys]340 * @returns {Object} The resulting value of object a341 */342const extend = (a, b, thisArg, {allOwnKeys}= {}) => {343 forEach(b, (val, key) => {344 if (thisArg && isFunction(val)) {345 a[key] = bind(val, thisArg);346 } else {347 a[key] = val;348 }349 }, {allOwnKeys});350 return a;351}352 353/**354 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)355 *356 * @param {string} content with BOM357 *358 * @returns {string} content value without BOM359 */360const stripBOM = (content) => {361 if (content.charCodeAt(0) === 0xFEFF) {362 content = content.slice(1);363 }364 return content;365}366 367/**368 * Inherit the prototype methods from one constructor into another369 * @param {function} constructor370 * @param {function} superConstructor371 * @param {object} [props]372 * @param {object} [descriptors]373 *374 * @returns {void}375 */376const inherits = (constructor, superConstructor, props, descriptors) => {377 constructor.prototype = Object.create(superConstructor.prototype, descriptors);378 constructor.prototype.constructor = constructor;379 Object.defineProperty(constructor, 'super', {380 value: superConstructor.prototype381 });382 props && Object.assign(constructor.prototype, props);383}384 385/**386 * Resolve object with deep prototype chain to a flat object387 * @param {Object} sourceObj source object388 * @param {Object} [destObj]389 * @param {Function|Boolean} [filter]390 * @param {Function} [propFilter]391 *392 * @returns {Object}393 */394const toFlatObject = (sourceObj, destObj, filter, propFilter) => {395 let props;396 let i;397 let prop;398 const merged = {};399 400 destObj = destObj || {};401 // eslint-disable-next-line no-eq-null,eqeqeq402 if (sourceObj == null) return destObj;403 404 do {405 props = Object.getOwnPropertyNames(sourceObj);406 i = props.length;407 while (i-- > 0) {408 prop = props[i];409 if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) {410 destObj[prop] = sourceObj[prop];411 merged[prop] = true;412 }413 }414 sourceObj = filter !== false && getPrototypeOf(sourceObj);415 } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);416 417 return destObj;418}419 420/**421 * Determines whether a string ends with the characters of a specified string422 *423 * @param {String} str424 * @param {String} searchString425 * @param {Number} [position= 0]426 *427 * @returns {boolean}428 */429const endsWith = (str, searchString, position) => {430 str = String(str);431 if (position === undefined || position > str.length) {432 position = str.length;433 }434 position -= searchString.length;435 const lastIndex = str.indexOf(searchString, position);436 return lastIndex !== -1 && lastIndex === position;437}438 439 440/**441 * Returns new array from array like object or null if failed442 *443 * @param {*} [thing]444 *445 * @returns {?Array}446 */447const toArray = (thing) => {448 if (!thing) return null;449 if (isArray(thing)) return thing;450 let i = thing.length;451 if (!isNumber(i)) return null;452 const arr = new Array(i);453 while (i-- > 0) {454 arr[i] = thing[i];455 }456 return arr;457}458 459/**460 * Checking if the Uint8Array exists and if it does, it returns a function that checks if the461 * thing passed in is an instance of Uint8Array462 *463 * @param {TypedArray}464 *465 * @returns {Array}466 */467// eslint-disable-next-line func-names468const isTypedArray = (TypedArray => {469 // eslint-disable-next-line func-names470 return thing => {471 return TypedArray && thing instanceof TypedArray;472 };473})(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array));474 475/**476 * For each entry in the object, call the function with the key and value.477 *478 * @param {Object<any, any>} obj - The object to iterate over.479 * @param {Function} fn - The function to call for each entry.480 *481 * @returns {void}482 */483const forEachEntry = (obj, fn) => {484 const generator = obj && obj[Symbol.iterator];485 486 const iterator = generator.call(obj);487 488 let result;489 490 while ((result = iterator.next()) && !result.done) {491 const pair = result.value;492 fn.call(obj, pair[0], pair[1]);493 }494}495 496/**497 * It takes a regular expression and a string, and returns an array of all the matches498 *499 * @param {string} regExp - The regular expression to match against.500 * @param {string} str - The string to search.501 *502 * @returns {Array<boolean>}503 */504const matchAll = (regExp, str) => {505 let matches;506 const arr = [];507 508 while ((matches = regExp.exec(str)) !== null) {509 arr.push(matches);510 }511 512 return arr;513}514 515/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */516const isHTMLForm = kindOfTest('HTMLFormElement');517 518const toCamelCase = str => {519 return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,520 function replacer(m, p1, p2) {521 return p1.toUpperCase() + p2;522 }523 );524};525 526/* Creating a function that will check if an object has a property. */527const hasOwnProperty = (({hasOwnProperty}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype);528 529/**530 * Determine if a value is a RegExp object531 *532 * @param {*} val The value to test533 *534 * @returns {boolean} True if value is a RegExp object, otherwise false535 */536const isRegExp = kindOfTest('RegExp');537 538const reduceDescriptors = (obj, reducer) => {539 const descriptors = Object.getOwnPropertyDescriptors(obj);540 const reducedDescriptors = {};541 542 forEach(descriptors, (descriptor, name) => {543 let ret;544 if ((ret = reducer(descriptor, name, obj)) !== false) {545 reducedDescriptors[name] = ret || descriptor;546 }547 });548 549 Object.defineProperties(obj, reducedDescriptors);550}551 552/**553 * Makes all methods read-only554 * @param {Object} obj555 */556 557const freezeMethods = (obj) => {558 reduceDescriptors(obj, (descriptor, name) => {559 // skip restricted props in strict mode560 if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) {561 return false;562 }563 564 const value = obj[name];565 566 if (!isFunction(value)) return;567 568 descriptor.enumerable = false;569 570 if ('writable' in descriptor) {571 descriptor.writable = false;572 return;573 }574 575 if (!descriptor.set) {576 descriptor.set = () => {577 throw Error('Can not rewrite read-only method \'' + name + '\'');578 };579 }580 });581}582 583const toObjectSet = (arrayOrString, delimiter) => {584 const obj = {};585 586 const define = (arr) => {587 arr.forEach(value => {588 obj[value] = true;589 });590 }591 592 isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));593 594 return obj;595}596 597const noop = () => {}598 599const toFiniteNumber = (value, defaultValue) => {600 value = +value;601 return Number.isFinite(value) ? value : defaultValue;602}603 604const ALPHA = 'abcdefghijklmnopqrstuvwxyz'605 606const DIGIT = '0123456789';607 608const ALPHABET = {609 DIGIT,610 ALPHA,611 ALPHA_DIGIT: ALPHA + ALPHA.toUpperCase() + DIGIT612}613 614const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => {615 let str = '';616 const {length} = alphabet;617 while (size--) {618 str += alphabet[Math.random() * length|0]619 }620 621 return str;622}623 624/**625 * If the thing is a FormData object, return true, otherwise return false.626 *627 * @param {unknown} thing - The thing to check.628 *629 * @returns {boolean}630 */631function isSpecCompliantForm(thing) {632 return !!(thing && isFunction(thing.append) && thing[Symbol.toStringTag] === 'FormData' && thing[Symbol.iterator]);633}634 635const toJSONObject = (obj) => {636 const stack = new Array(10);637 638 const visit = (source, i) => {639 640 if (isObject(source)) {641 if (stack.indexOf(source) >= 0) {642 return;643 }644 645 if(!('toJSON' in source)) {646 stack[i] = source;647 const target = isArray(source) ? [] : {};648 649 forEach(source, (value, key) => {650 const reducedValue = visit(value, i + 1);651 !isUndefined(reducedValue) && (target[key] = reducedValue);652 });653 654 stack[i] = undefined;655 656 return target;657 }658 }659 660 return source;661 }662 663 return visit(obj, 0);664}665 666const isAsyncFn = kindOfTest('AsyncFunction');667 668const isThenable = (thing) =>669 thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch);670 671export default {672 isArray,673 isArrayBuffer,674 isBuffer,675 isFormData,676 isArrayBufferView,677 isString,678 isNumber,679 isBoolean,680 isObject,681 isPlainObject,682 isUndefined,683 isDate,684 isFile,685 isBlob,686 isRegExp,687 isFunction,688 isStream,689 isURLSearchParams,690 isTypedArray,691 isFileList,692 forEach,693 merge,694 extend,695 trim,696 stripBOM,697 inherits,698 toFlatObject,699 kindOf,700 kindOfTest,701 endsWith,702 toArray,703 forEachEntry,704 matchAll,705 isHTMLForm,706 hasOwnProperty,707 hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection708 reduceDescriptors,709 freezeMethods,710 toObjectSet,711 toCamelCase,712 noop,713 toFiniteNumber,714 findKey,715 global: _global,716 isContextDefined,717 ALPHABET,718 generateString,719 isSpecCompliantForm,720 toJSONObject,721 isAsyncFn,722 isThenable723};724 