1 | 'use strict';
|
2 |
|
3 | import bind from './helpers/bind.js';
|
4 |
|
5 |
|
6 |
|
7 | const {toString} = Object.prototype;
|
8 | const {getPrototypeOf} = Object;
|
9 |
|
10 | const 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 |
|
15 | const kindOfTest = (type) => {
|
16 | type = type.toLowerCase();
|
17 | return (thing) => kindOf(thing) === type
|
18 | }
|
19 |
|
20 | const typeOfTest = type => thing => typeof thing === type;
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | const {isArray} = Array;
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | const isUndefined = typeOfTest('undefined');
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 | function 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 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 | const isArrayBuffer = kindOfTest('ArrayBuffer');
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 | function 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 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 | const isString = typeOfTest('string');
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 | const isFunction = typeOfTest('function');
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | const isNumber = typeOfTest('number');
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 | const isObject = (thing) => thing !== null && typeof thing === 'object';
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 | const isBoolean = thing => thing === true || thing === false;
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 | const 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 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 | const isDate = kindOfTest('Date');
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 | const isFile = kindOfTest('File');
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 | const isBlob = kindOfTest('Blob');
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | const isFileList = kindOfTest('FileList');
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 | const isStream = (val) => isObject(val) && isFunction(val.pipe);
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 | const isFormData = (thing) => {
|
191 | const pattern = '[object FormData]';
|
192 | return thing && (
|
193 | (typeof FormData === 'function' && thing instanceof FormData) ||
|
194 | toString.call(thing) === pattern ||
|
195 | (isFunction(thing.toString) && thing.toString() === pattern)
|
196 | );
|
197 | }
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | const isURLSearchParams = kindOfTest('URLSearchParams');
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 | const trim = (str) => str.trim ?
|
216 | str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 | function forEach(obj, fn, {allOwnKeys = false} = {}) {
|
234 |
|
235 | if (obj === null || typeof obj === 'undefined') {
|
236 | return;
|
237 | }
|
238 |
|
239 | let i;
|
240 | let l;
|
241 |
|
242 |
|
243 | if (typeof obj !== 'object') {
|
244 |
|
245 | obj = [obj];
|
246 | }
|
247 |
|
248 | if (isArray(obj)) {
|
249 |
|
250 | for (i = 0, l = obj.length; i < l; i++) {
|
251 | fn.call(null, obj[i], i, obj);
|
252 | }
|
253 | } else {
|
254 |
|
255 | const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
|
256 | const len = keys.length;
|
257 | let key;
|
258 |
|
259 | for (i = 0; i < len; i++) {
|
260 | key = keys[i];
|
261 | fn.call(null, obj[key], key, obj);
|
262 | }
|
263 | }
|
264 | }
|
265 |
|
266 | function findKey(obj, key) {
|
267 | key = key.toLowerCase();
|
268 | const keys = Object.keys(obj);
|
269 | let i = keys.length;
|
270 | let _key;
|
271 | while (i-- > 0) {
|
272 | _key = keys[i];
|
273 | if (key === _key.toLowerCase()) {
|
274 | return _key;
|
275 | }
|
276 | }
|
277 | return null;
|
278 | }
|
279 |
|
280 | const _global = (() => {
|
281 |
|
282 | if (typeof globalThis !== "undefined") return globalThis;
|
283 | return typeof self !== "undefined" ? self : (typeof window !== 'undefined' ? window : global)
|
284 | })();
|
285 |
|
286 | const isContextDefined = (context) => !isUndefined(context) && context !== _global;
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 | function merge(/* obj1, obj2, obj3, ... */) {
|
307 | const {caseless} = isContextDefined(this) && this || {};
|
308 | const result = {};
|
309 | const assignValue = (val, key) => {
|
310 | const targetKey = caseless && findKey(result, key) || key;
|
311 | if (isPlainObject(result[targetKey]) && isPlainObject(val)) {
|
312 | result[targetKey] = merge(result[targetKey], val);
|
313 | } else if (isPlainObject(val)) {
|
314 | result[targetKey] = merge({}, val);
|
315 | } else if (isArray(val)) {
|
316 | result[targetKey] = val.slice();
|
317 | } else {
|
318 | result[targetKey] = val;
|
319 | }
|
320 | }
|
321 |
|
322 | for (let i = 0, l = arguments.length; i < l; i++) {
|
323 | arguments[i] && forEach(arguments[i], assignValue);
|
324 | }
|
325 | return result;
|
326 | }
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 | const extend = (a, b, thisArg, {allOwnKeys}= {}) => {
|
339 | forEach(b, (val, key) => {
|
340 | if (thisArg && isFunction(val)) {
|
341 | a[key] = bind(val, thisArg);
|
342 | } else {
|
343 | a[key] = val;
|
344 | }
|
345 | }, {allOwnKeys});
|
346 | return a;
|
347 | }
|
348 |
|
349 |
|
350 |
|
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 | const stripBOM = (content) => {
|
357 | if (content.charCodeAt(0) === 0xFEFF) {
|
358 | content = content.slice(1);
|
359 | }
|
360 | return content;
|
361 | }
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 | const inherits = (constructor, superConstructor, props, descriptors) => {
|
373 | constructor.prototype = Object.create(superConstructor.prototype, descriptors);
|
374 | constructor.prototype.constructor = constructor;
|
375 | Object.defineProperty(constructor, 'super', {
|
376 | value: superConstructor.prototype
|
377 | });
|
378 | props && Object.assign(constructor.prototype, props);
|
379 | }
|
380 |
|
381 | /**
|
382 | * Resolve object with deep prototype chain to a flat object
|
383 | * @param {Object} sourceObj source object
|
384 | * @param {Object} [destObj]
|
385 | * @param {Function|Boolean} [filter]
|
386 | * @param {Function} [propFilter]
|
387 | *
|
388 | * @returns {Object}
|
389 | */
|
390 | const toFlatObject = (sourceObj, destObj, filter, propFilter) => {
|
391 | let props;
|
392 | let i;
|
393 | let prop;
|
394 | const merged = {};
|
395 |
|
396 | destObj = destObj || {};
|
397 |
|
398 | if (sourceObj == null) return destObj;
|
399 |
|
400 | do {
|
401 | props = Object.getOwnPropertyNames(sourceObj);
|
402 | i = props.length;
|
403 | while (i-- > 0) {
|
404 | prop = props[i];
|
405 | if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) {
|
406 | destObj[prop] = sourceObj[prop];
|
407 | merged[prop] = true;
|
408 | }
|
409 | }
|
410 | sourceObj = filter !== false && getPrototypeOf(sourceObj);
|
411 | } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
|
412 |
|
413 | return destObj;
|
414 | }
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 | const endsWith = (str, searchString, position) => {
|
426 | str = String(str);
|
427 | if (position === undefined || position > str.length) {
|
428 | position = str.length;
|
429 | }
|
430 | position -= searchString.length;
|
431 | const lastIndex = str.indexOf(searchString, position);
|
432 | return lastIndex !== -1 && lastIndex === position;
|
433 | }
|
434 |
|
435 |
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 | const toArray = (thing) => {
|
444 | if (!thing) return null;
|
445 | if (isArray(thing)) return thing;
|
446 | let i = thing.length;
|
447 | if (!isNumber(i)) return null;
|
448 | const arr = new Array(i);
|
449 | while (i-- > 0) {
|
450 | arr[i] = thing[i];
|
451 | }
|
452 | return arr;
|
453 | }
|
454 |
|
455 |
|
456 |
|
457 |
|
458 |
|
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 | const isTypedArray = (TypedArray => {
|
465 |
|
466 | return thing => {
|
467 | return TypedArray && thing instanceof TypedArray;
|
468 | };
|
469 | })(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array));
|
470 |
|
471 |
|
472 |
|
473 |
|
474 |
|
475 |
|
476 |
|
477 |
|
478 |
|
479 | const forEachEntry = (obj, fn) => {
|
480 | const generator = obj && obj[Symbol.iterator];
|
481 |
|
482 | const iterator = generator.call(obj);
|
483 |
|
484 | let result;
|
485 |
|
486 | while ((result = iterator.next()) && !result.done) {
|
487 | const pair = result.value;
|
488 | fn.call(obj, pair[0], pair[1]);
|
489 | }
|
490 | }
|
491 |
|
492 |
|
493 |
|
494 |
|
495 |
|
496 |
|
497 |
|
498 |
|
499 |
|
500 | const matchAll = (regExp, str) => {
|
501 | let matches;
|
502 | const arr = [];
|
503 |
|
504 | while ((matches = regExp.exec(str)) !== null) {
|
505 | arr.push(matches);
|
506 | }
|
507 |
|
508 | return arr;
|
509 | }
|
510 |
|
511 |
|
512 | const isHTMLForm = kindOfTest('HTMLFormElement');
|
513 |
|
514 | const toCamelCase = str => {
|
515 | return str.toLowerCase().replace(/[_-\s]([a-z\d])(\w*)/g,
|
516 | function replacer(m, p1, p2) {
|
517 | return p1.toUpperCase() + p2;
|
518 | }
|
519 | );
|
520 | };
|
521 |
|
522 |
|
523 | const hasOwnProperty = (({hasOwnProperty}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype);
|
524 |
|
525 |
|
526 |
|
527 |
|
528 |
|
529 |
|
530 |
|
531 |
|
532 | const isRegExp = kindOfTest('RegExp');
|
533 |
|
534 | const reduceDescriptors = (obj, reducer) => {
|
535 | const descriptors = Object.getOwnPropertyDescriptors(obj);
|
536 | const reducedDescriptors = {};
|
537 |
|
538 | forEach(descriptors, (descriptor, name) => {
|
539 | if (reducer(descriptor, name, obj) !== false) {
|
540 | reducedDescriptors[name] = descriptor;
|
541 | }
|
542 | });
|
543 |
|
544 | Object.defineProperties(obj, reducedDescriptors);
|
545 | }
|
546 |
|
547 |
|
548 |
|
549 |
|
550 |
|
551 |
|
552 | const freezeMethods = (obj) => {
|
553 | reduceDescriptors(obj, (descriptor, name) => {
|
554 |
|
555 | if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) {
|
556 | return false;
|
557 | }
|
558 |
|
559 | const value = obj[name];
|
560 |
|
561 | if (!isFunction(value)) return;
|
562 |
|
563 | descriptor.enumerable = false;
|
564 |
|
565 | if ('writable' in descriptor) {
|
566 | descriptor.writable = false;
|
567 | return;
|
568 | }
|
569 |
|
570 | if (!descriptor.set) {
|
571 | descriptor.set = () => {
|
572 | throw Error('Can not rewrite read-only method \'' + name + '\'');
|
573 | };
|
574 | }
|
575 | });
|
576 | }
|
577 |
|
578 | const toObjectSet = (arrayOrString, delimiter) => {
|
579 | const obj = {};
|
580 |
|
581 | const define = (arr) => {
|
582 | arr.forEach(value => {
|
583 | obj[value] = true;
|
584 | });
|
585 | }
|
586 |
|
587 | isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));
|
588 |
|
589 | return obj;
|
590 | }
|
591 |
|
592 | const noop = () => {}
|
593 |
|
594 | const toFiniteNumber = (value, defaultValue) => {
|
595 | value = +value;
|
596 | return Number.isFinite(value) ? value : defaultValue;
|
597 | }
|
598 |
|
599 | const toJSONObject = (obj) => {
|
600 | const stack = new Array(10);
|
601 |
|
602 | const visit = (source, i) => {
|
603 |
|
604 | if (isObject(source)) {
|
605 | if (stack.indexOf(source) >= 0) {
|
606 | return;
|
607 | }
|
608 |
|
609 | if(!('toJSON' in source)) {
|
610 | stack[i] = source;
|
611 | const target = isArray(source) ? [] : {};
|
612 |
|
613 | forEach(source, (value, key) => {
|
614 | const reducedValue = visit(value, i + 1);
|
615 | !isUndefined(reducedValue) && (target[key] = reducedValue);
|
616 | });
|
617 |
|
618 | stack[i] = undefined;
|
619 |
|
620 | return target;
|
621 | }
|
622 | }
|
623 |
|
624 | return source;
|
625 | }
|
626 |
|
627 | return visit(obj, 0);
|
628 | }
|
629 |
|
630 | export default {
|
631 | isArray,
|
632 | isArrayBuffer,
|
633 | isBuffer,
|
634 | isFormData,
|
635 | isArrayBufferView,
|
636 | isString,
|
637 | isNumber,
|
638 | isBoolean,
|
639 | isObject,
|
640 | isPlainObject,
|
641 | isUndefined,
|
642 | isDate,
|
643 | isFile,
|
644 | isBlob,
|
645 | isRegExp,
|
646 | isFunction,
|
647 | isStream,
|
648 | isURLSearchParams,
|
649 | isTypedArray,
|
650 | isFileList,
|
651 | forEach,
|
652 | merge,
|
653 | extend,
|
654 | trim,
|
655 | stripBOM,
|
656 | inherits,
|
657 | toFlatObject,
|
658 | kindOf,
|
659 | kindOfTest,
|
660 | endsWith,
|
661 | toArray,
|
662 | forEachEntry,
|
663 | matchAll,
|
664 | isHTMLForm,
|
665 | hasOwnProperty,
|
666 | hasOwnProp: hasOwnProperty,
|
667 | reduceDescriptors,
|
668 | freezeMethods,
|
669 | toObjectSet,
|
670 | toCamelCase,
|
671 | noop,
|
672 | toFiniteNumber,
|
673 | findKey,
|
674 | global: _global,
|
675 | isContextDefined,
|
676 | toJSONObject
|
677 | };
|