mic-inspector
Version:
A react inspector which a most similar of Chorme DevTools inspector
112 lines (111 loc) • 4.29 kB
JavaScript
import React, { useMemo } from 'react';
import { DescriptorValueType, DescriptorNameType } from '../named-descriptor/types';
import { Property } from '../property';
import { ObjectValueSeparator } from './types';
import { getNamedDescriptors } from '../named-descriptor/locale';
import { isObjectOrFunction } from '../property-value/locale';
export const { Object, Node } = window;
export const arraylikeMethodNames = [...(!window.Symbol ? [] : [Symbol.iterator]), 'entries', 'forEach', 'item', 'keys', 'splice', 'values'];
/**
* Returns a string represents object name
* @param value An object
* @param isNode A boolean represents whether the object is a node
*/
export const getObjectName = (value, isNode) => {
// if the object is a node
if (isNode) {
try {
const nodeName = value.nodeName.toLocaleLowerCase();
return nodeName[0] === '#' ? nodeName.substring(1) : nodeName;
}
catch (e) { }
}
const constructor = value === null || value === void 0 ? void 0 : value.constructor;
return constructor === Object && value !== Object.prototype ? '' : constructor === null || constructor === void 0 ? void 0 : constructor.name;
};
/**
* A method to fitler object subs
* @param param0 A descriptor of the object
* @param arraylike A boolean represents whether the object is an array
*/
export const objectSubsFilter = ({ get, set, nameType, valueType, value, enumerable }, arraylike) => {
// if the object is an array
if (arraylike) {
return (nameType & DescriptorNameType.Index) === DescriptorNameType.Index;
}
// if the accessors existed
if (get || set) {
return false;
}
switch (true) {
case (valueType & DescriptorValueType.Normal) === DescriptorValueType.Normal:
case (valueType & DescriptorValueType.Result) === DescriptorValueType.Result:
break;
default:
return false;
}
return !isObjectOrFunction(value) || enumerable;
};
/**
* A method to render object subs
* @param object The object value
* @param arraylike A boolean represents whether the object is an array
* @param maxPropertyLength A number represents the length of object properties to preview
*/
export const renderObjectSubs = (object, arraylike, maxPropertyLength = 5) => {
const objectSubs = [];
// for each descriptors
for (const descriptor of getNamedDescriptors(object)) {
const { length } = objectSubs;
// if the length is greater than maxPropertyLength * 2
if (length >= maxPropertyLength * 2) {
break;
}
// if descriptor has filtered
if (!objectSubsFilter(descriptor, arraylike)) {
continue;
}
objectSubs.push(React.createElement(Property, { key: length, descriptor: descriptor, preview: true }), React.createElement("i", { key: length + 1, "data-separator": ObjectValueSeparator.Comma }, ","));
}
// if the length of subs is less than maxPropertyLength * 2
if (objectSubs.length < maxPropertyLength * 2) {
// remove the last one that the comma element
objectSubs.splice(objectSubs.length - 1, 1);
}
else {
objectSubs.push(React.createElement("i", { key: objectSubs.length + 1, "data-separator": ObjectValueSeparator.Spread }, "..."));
}
return objectSubs;
};
/**
* Get the array info
* @param value An object that maybe is an array
*/
export const useArrayInfo = (value) => {
return useMemo(() => {
tryBlock: try {
// if the object is an array
if (Array.isArray(value)) {
break tryBlock;
}
// the the length property in the object
if ('length' in value) {
// for each array method names
for (const name of arraylikeMethodNames) {
// if this method is a function
if (typeof value[name] === 'function') {
break tryBlock;
}
}
}
return [false, 0];
}
catch (e) { }
let length = 0;
try {
length = value.length;
}
catch (e) { }
return [true, length];
}, [value]);
};