UNPKG

@msom/common

Version:

@msom/common

148 lines (135 loc) 3.73 kB
import { Collection } from "../collection"; import { IPermission, createPermission } from "../permission"; const symbolKeys = new Collection<{ key: string; symbolKey: symbol }>( (keys) => keys.key ); export function GeneratSymbolKey(key: string): symbol { if (symbolKeys.hasKey(key)) { return symbolKeys.get(key)!.symbolKey; } else { const symbolKey = Symbol(key); symbolKeys.add({ key, symbolKey }); return symbolKey; } } export function setGlobalData<T>(key: string, data: T): T { const symbolKey = GeneratSymbolKey(key); Object.assign(globalThis, { [symbolKey]: data }); return data; } export function getGlobalData(key: string): unknown { const symbolKey = GeneratSymbolKey(key); const data = Reflect.get(globalThis, symbolKey); if (!data) { if (key.startsWith("@msom/")) { throw `The GlobalData of ${key} is must init before get.`; } return setGlobalData(key, {}); } return data; } export type Nullable = null | undefined; export type createFunction<T extends unknown[]> = T extends [ ...infer P, infer R ] ? (...args: P) => R : never; const propertyPermission = { enumerable: 0b100, writable: 0b010, configurable: 0b001, }; export const PropertyPermission = createPermission(propertyPermission); /** * @param target * @param propKey * @param permission 7 * * const enumerable = 0b100; * * const writable = 0b010; * * const configurable = 0b001; * @param value */ export function defineProperty<T>( target: T, propKey: string | symbol, permission: IPermission<typeof propertyPermission> | number = 7, value?: unknown ) { permission = PropertyPermission.from(permission); Object.defineProperty(target, propKey, { ...permission.get(), value, }); } /** * @param target * @param propKey * @param permission [0-5] * * const configurable = 0b001; * * const enumerable = 0b100; * * 访问器属性修饰符无法设置writable * @param getter * @param setter */ export function defineAccesser<T, R>( target: T, propKey: symbol | string, permission: IPermission<typeof propertyPermission> | number = 5, getter?: () => R, setter?: (value: R) => void ) { permission = PropertyPermission.from(permission); Object.defineProperty<T>( target, propKey, Object.assign( { ...permission.get("configurable", "enumerable"), }, getter && { get: function (this: T) { return getter.call(this); }, }, setter && { set: function (this: T, value: R) { return setter.call(this, value); }, } ) ); } export function tryCall<F extends createFunction<[...unknown[], unknown]>>( call: F, data?: Parameters<F>, receiver?: unknown ): ReturnType<F> { if (typeof call === "function") { try { return Reflect.apply(call, receiver, data || []) as ReturnType<F>; } catch (e: any) { throw e instanceof Error ? e : new Error(e); } } else { throw `${ typeof call === "object" ? Reflect.get(call, "name", call) : Object(call).toString() } is not a function.`; } } export function equal(value: unknown, otherValue: unknown): boolean { return Object.is(value, otherValue); } export function ownKeysAndPrototypeOwnKeys( $events: object, keys: Collection<PropertyKey> = new Collection((key) => key) ) { Object.keys($events).forEach((key) => keys.add(key)); const prototype = Reflect.getPrototypeOf($events); if (prototype) { ownKeysAndPrototypeOwnKeys(prototype, keys); } return keys; }