isClass = {
const getProto = globalThis.Reflect?.getPrototypeOf
? globalThis.Reflect.getPrototypeOf.bind(globalThis.Reflect)
: Object.getPrototypeOf.bind(Object);
const setDesc = globalThis.Reflect?.defineProperty
? globalThis.Reflect.defineProperty.bind(globalThis.Reflect)
: Object.defineProperty.bind(Object);
const getOwnStringKeys = globalThis.Reflect?.ownKeys
? globalThis.Reflect.ownKeys.bind(globalThis.Reflect)
: Object.getOwnPropertyNames.bind(Object);
setDesc(isClass, "proto", {
enumerable: true,
value: isClassOrProto
});
for (let name of "BigInt Boolean Function Number Object String Symbol".split(/\s+/)) {
if (typeof globalThis[name] === "function" && typeOf(globalThis[name]) === "function") {
let f = function(value) {
return this(name, value);
}
setDesc(f, "name", {
enumerable: true,
configurable: true,
get: () => `is${name}`
});
isClass[name] || setDesc(isClass, name, {
enumerable: true,
value: f
});
isClassOrProto[name] || setDesc(isClassOrProto, name, {
enumerable: true,
value: f
});
}
}
return isClass;
// const protoNames = new Set("bigint boolean null number string symbol undefined".split(/\s+/));
// const realms = new WeakMap();
function isClassOrProto(className, value) {
let t = typeOf(value);
switch (t) {
case "function":
case "object":
return isClass(className, value);
}
return classToString(className).toLowerCase() === typeOf(value);
}
function isClass(className, value) {
switch (typeOf(value)) {
case "function":
case "object":
break;
default:
return false;
}
if (className === null) { return getProto(value) === null; }
if (getProto(value) === null) { return false; }
className = classToString(className);
let global;
if (value instanceof {}.constructor) {
// this realm
global = globalThis;
} else {
// other realm
let v, p;
v = value;
while (true) {
p = getProto(v);
if (p === null) { break; }
v = p;
}
let Object = v.constructor;
global = new (Object.getPrototypeOf(Object).constructor)(`return globalThis ?? this;`)();
if (global.globalThis !== global) { return null; }
}
let targetProto, p;
if (className in global && isObj(global[className]) && value instanceof global[className]) {
targetProto = global[className].prototype;
if ((p = getProto(value)) === targetProto) { return true; }
while (p !== null) {
p = getProto(p);
if (p === targetProto) { return true; }
}
}
return false;
}
function classToString(className) {
return typeof className === "string"
? className
: (className = String(typeof className === "function" ? (className.name || className) : className));
}
function isObj(value) {
switch (typeOf(value)) {
case "object":
case "function":
return true;
}
return false;
}
}