🚨 upgrade to follow eslint new rules (#1179)

This commit is contained in:
Kuitos 2020-12-24 12:25:36 +08:00 committed by GitHub
parent 5b206f20bc
commit aa84eaa289
19 changed files with 76 additions and 55 deletions

View File

@ -3,7 +3,7 @@
* @since 2020-05-15 * @since 2020-05-15
*/ */
import { FrameworkLifeCycles } from '../interfaces'; import type { FrameworkLifeCycles } from '../interfaces';
export default function getAddOn(global: Window): FrameworkLifeCycles<any> { export default function getAddOn(global: Window): FrameworkLifeCycles<any> {
return { return {

View File

@ -4,12 +4,12 @@
*/ */
import { concat, mergeWith } from 'lodash'; import { concat, mergeWith } from 'lodash';
import { FrameworkLifeCycles } from '../interfaces'; import type { FrameworkLifeCycles, ObjectType } from '../interfaces';
import getRuntimePublicPathAddOn from './runtimePublicPath'; import getRuntimePublicPathAddOn from './runtimePublicPath';
import getEngineFlagAddon from './engineFlag'; import getEngineFlagAddon from './engineFlag';
export default function getAddOns<T extends object>(global: Window, publicPath: string): FrameworkLifeCycles<T> { export default function getAddOns<T extends ObjectType>(global: Window, publicPath: string): FrameworkLifeCycles<T> {
return mergeWith({}, getEngineFlagAddon(global), getRuntimePublicPathAddOn(global, publicPath), (v1, v2) => return mergeWith({}, getEngineFlagAddon(global), getRuntimePublicPathAddOn(global, publicPath), (v1, v2) =>
concat(v1 ?? [], v2 ?? []), concat(v1 ?? [], v2 ?? []),
); );

View File

@ -2,7 +2,7 @@
* @author Kuitos * @author Kuitos
* @since 2019-11-12 * @since 2019-11-12
*/ */
import { FrameworkLifeCycles } from '../interfaces'; import type { FrameworkLifeCycles } from '../interfaces';
const rawPublicPath = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; const rawPublicPath = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;

View File

@ -1,17 +1,20 @@
import { noop } from 'lodash'; import { noop } from 'lodash';
import { mountRootParcel, ParcelConfigObject, registerApplication, start as startSingleSpa } from 'single-spa'; import type { ParcelConfigObject } from 'single-spa';
import { FrameworkConfiguration, FrameworkLifeCycles, LoadableApp, MicroApp, RegistrableApp } from './interfaces'; import { mountRootParcel, registerApplication, start as startSingleSpa } from 'single-spa';
import { loadApp, ParcelConfigObjectGetter } from './loader'; import type { ObjectType } from './interfaces';
import type { FrameworkConfiguration, FrameworkLifeCycles, LoadableApp, MicroApp, RegistrableApp } from './interfaces';
import type { ParcelConfigObjectGetter } from './loader';
import { loadApp } from './loader';
import { doPrefetchStrategy } from './prefetch'; import { doPrefetchStrategy } from './prefetch';
import { Deferred, getContainer, getXPathForElement, toArray } from './utils'; import { Deferred, getContainer, getXPathForElement, toArray } from './utils';
let microApps: RegistrableApp[] = []; let microApps: Array<RegistrableApp<Record<string, unknown>>> = [];
// eslint-disable-next-line import/no-mutable-exports // eslint-disable-next-line import/no-mutable-exports
export let frameworkConfiguration: FrameworkConfiguration = {}; export let frameworkConfiguration: FrameworkConfiguration = {};
const frameworkStartedDefer = new Deferred<void>(); const frameworkStartedDefer = new Deferred<void>();
export function registerMicroApps<T extends object = {}>( export function registerMicroApps<T extends ObjectType>(
apps: Array<RegistrableApp<T>>, apps: Array<RegistrableApp<T>>,
lifeCycles?: FrameworkLifeCycles<T>, lifeCycles?: FrameworkLifeCycles<T>,
) { ) {
@ -46,7 +49,7 @@ export function registerMicroApps<T extends object = {}>(
const appConfigPromiseGetterMap = new Map<string, Promise<ParcelConfigObjectGetter>>(); const appConfigPromiseGetterMap = new Map<string, Promise<ParcelConfigObjectGetter>>();
export function loadMicroApp<T extends object = {}>( export function loadMicroApp<T extends ObjectType>(
app: LoadableApp<T>, app: LoadableApp<T>,
configuration?: FrameworkConfiguration, configuration?: FrameworkConfiguration,
lifeCycles?: FrameworkLifeCycles<T>, lifeCycles?: FrameworkLifeCycles<T>,

View File

@ -4,7 +4,7 @@
*/ */
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import { OnGlobalStateChangeCallback, MicroAppStateActions } from './interfaces'; import type { OnGlobalStateChangeCallback, MicroAppStateActions } from './interfaces';
let globalState: Record<string, any> = {}; let globalState: Record<string, any> = {};

View File

@ -2,10 +2,11 @@
* @author kuitos * @author kuitos
* @since 2019-05-16 * @since 2019-05-16
*/ */
import { ImportEntryOpts } from 'import-html-entry'; import type { ImportEntryOpts } from 'import-html-entry';
import { RegisterApplicationConfig, StartOpts, Parcel } from 'single-spa'; import type { RegisterApplicationConfig, StartOpts, Parcel } from 'single-spa';
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Window { interface Window {
__POWERED_BY_QIANKUN__?: boolean; __POWERED_BY_QIANKUN__?: boolean;
__INJECTED_PUBLIC_PATH_BY_QIANKUN__?: string; __INJECTED_PUBLIC_PATH_BY_QIANKUN__?: string;
@ -13,6 +14,8 @@ declare global {
} }
} }
export type ObjectType = Record<string, unknown>;
export type Entry = export type Entry =
| string | string
| { | {
@ -31,7 +34,9 @@ export type AppMetadata = {
}; };
// just for manual loaded apps, in single-spa it called parcel // just for manual loaded apps, in single-spa it called parcel
export type LoadableApp<T extends object = {}> = AppMetadata & { /* props pass through to app */ props?: T } & ( export type LoadableApp<T extends ObjectType> = AppMetadata & {
/* props pass through to app */ props?: T;
} & (
| { | {
// legacy mode, the render function all handled by user // legacy mode, the render function all handled by user
render: HTMLContentRender; render: HTMLContentRender;
@ -43,7 +48,7 @@ export type LoadableApp<T extends object = {}> = AppMetadata & { /* props pass t
); );
// for the route-based apps // for the route-based apps
export type RegistrableApp<T extends object = {}> = LoadableApp<T> & { export type RegistrableApp<T extends ObjectType> = LoadableApp<T> & {
loader?: (loading: boolean) => void; loader?: (loading: boolean) => void;
activeRule: RegisterApplicationConfig['activeWhen']; activeRule: RegisterApplicationConfig['activeWhen'];
}; };
@ -83,8 +88,8 @@ type QiankunSpecialOpts = {
}; };
export type FrameworkConfiguration = QiankunSpecialOpts & ImportEntryOpts & StartOpts; export type FrameworkConfiguration = QiankunSpecialOpts & ImportEntryOpts & StartOpts;
export type LifeCycleFn<T extends object> = (app: LoadableApp<T>, global: typeof window) => Promise<any>; export type LifeCycleFn<T extends ObjectType> = (app: LoadableApp<T>, global: typeof window) => Promise<any>;
export type FrameworkLifeCycles<T extends object> = { export type FrameworkLifeCycles<T extends ObjectType> = {
beforeLoad?: LifeCycleFn<T> | Array<LifeCycleFn<T>>; // function before app load beforeLoad?: LifeCycleFn<T> | Array<LifeCycleFn<T>>; // function before app load
beforeMount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>; // function before app mount beforeMount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>; // function before app mount
afterMount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>; // function after app mount afterMount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>; // function after app mount
@ -107,7 +112,7 @@ export enum SandBoxType {
LegacyProxy = 'LegacyProxy', LegacyProxy = 'LegacyProxy',
} }
export interface SandBox { export type SandBox = {
/** 沙箱的名字 */ /** 沙箱的名字 */
name: string; name: string;
/** 沙箱的类型 */ /** 沙箱的类型 */
@ -119,10 +124,10 @@ export interface SandBox {
/** latest set property */ /** latest set property */
latestSetProp?: PropertyKey | null; latestSetProp?: PropertyKey | null;
/** 启动沙箱 */ /** 启动沙箱 */
active(): void; active: () => void;
/** 关闭沙箱 */ /** 关闭沙箱 */
inactive(): void; inactive: () => void;
} };
export type OnGlobalStateChangeCallback = (state: Record<string, any>, prevState: Record<string, any>) => void; export type OnGlobalStateChangeCallback = (state: Record<string, any>, prevState: Record<string, any>) => void;

View File

@ -5,10 +5,17 @@
import { importEntry } from 'import-html-entry'; import { importEntry } from 'import-html-entry';
import { concat, forEach, mergeWith } from 'lodash'; import { concat, forEach, mergeWith } from 'lodash';
import { LifeCycles, ParcelConfigObject } from 'single-spa'; import type { LifeCycles, ParcelConfigObject } from 'single-spa';
import getAddOns from './addons'; import getAddOns from './addons';
import { getMicroAppStateActions } from './globalState'; import { getMicroAppStateActions } from './globalState';
import { FrameworkConfiguration, FrameworkLifeCycles, HTMLContentRender, LifeCycleFn, LoadableApp } from './interfaces'; import type {
FrameworkConfiguration,
FrameworkLifeCycles,
HTMLContentRender,
LifeCycleFn,
LoadableApp,
ObjectType,
} from './interfaces';
import { createSandboxContainer, css } from './sandbox'; import { createSandboxContainer, css } from './sandbox';
import { import {
Deferred, Deferred,
@ -32,7 +39,7 @@ function assertElementExist(element: Element | null | undefined, msg?: string) {
} }
} }
function execHooksChain<T extends object>( function execHooksChain<T extends ObjectType>(
hooks: Array<LifeCycleFn<T>>, hooks: Array<LifeCycleFn<T>>,
app: LoadableApp<T>, app: LoadableApp<T>,
global = window, global = window,
@ -44,7 +51,7 @@ function execHooksChain<T extends object>(
return Promise.resolve(); return Promise.resolve();
} }
async function validateSingularMode<T extends object>( async function validateSingularMode<T extends ObjectType>(
validate: FrameworkConfiguration['singular'], validate: FrameworkConfiguration['singular'],
app: LoadableApp<T>, app: LoadableApp<T>,
): Promise<boolean> { ): Promise<boolean> {
@ -238,7 +245,7 @@ let prevAppUnmountedDeferred: Deferred<void>;
export type ParcelConfigObjectGetter = (remountContainer?: string | HTMLElement) => ParcelConfigObject; export type ParcelConfigObjectGetter = (remountContainer?: string | HTMLElement) => ParcelConfigObject;
export async function loadApp<T extends object>( export async function loadApp<T extends ObjectType>(
app: LoadableApp<T>, app: LoadableApp<T>,
configuration: FrameworkConfiguration = {}, configuration: FrameworkConfiguration = {},
lifeCycles?: FrameworkLifeCycles<T>, lifeCycles?: FrameworkLifeCycles<T>,
@ -334,7 +341,7 @@ export async function loadApp<T extends object>(
onGlobalStateChange, onGlobalStateChange,
setGlobalState, setGlobalState,
offGlobalStateChange, offGlobalStateChange,
}: Record<string, Function> = getMicroAppStateActions(appInstanceId); }: Record<string, CallableFunction> = getMicroAppStateActions(appInstanceId);
// FIXME temporary way // FIXME temporary way
const syncAppWrapperElement2Sandbox = (element: HTMLElement | null) => (initialAppWrapperElement = element); const syncAppWrapperElement2Sandbox = (element: HTMLElement | null) => (initialAppWrapperElement = element);

View File

@ -3,10 +3,11 @@
* @since 2019-02-26 * @since 2019-02-26
*/ */
import { Entry, importEntry, ImportEntryOpts } from 'import-html-entry'; import type { Entry, ImportEntryOpts } from 'import-html-entry';
import { importEntry } from 'import-html-entry';
import { isFunction } from 'lodash'; import { isFunction } from 'lodash';
import { getAppStatus, getMountedApps, NOT_LOADED } from 'single-spa'; import { getAppStatus, getMountedApps, NOT_LOADED } from 'single-spa';
import { AppMetadata, PrefetchStrategy } from './interfaces'; import type { AppMetadata, PrefetchStrategy } from './interfaces';
type RequestIdleCallbackHandle = any; type RequestIdleCallbackHandle = any;
type RequestIdleCallbackOptions = { type RequestIdleCallbackOptions = {
@ -18,6 +19,7 @@ type RequestIdleCallbackDeadline = {
}; };
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Window { interface Window {
requestIdleCallback: ( requestIdleCallback: (
callback: (deadline: RequestIdleCallbackDeadline) => void, callback: (deadline: RequestIdleCallbackDeadline) => void,
@ -26,6 +28,7 @@ declare global {
cancelIdleCallback: (handle: RequestIdleCallbackHandle) => void; cancelIdleCallback: (handle: RequestIdleCallbackHandle) => void;
} }
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Navigator { interface Navigator {
connection: { connection: {
saveData: boolean; saveData: boolean;

View File

@ -8,8 +8,9 @@ import { getCurrentRunningSandboxProxy } from '../common';
import ProxySandbox from '../proxySandbox'; import ProxySandbox from '../proxySandbox';
declare global { declare global {
interface Window { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
[p: string]: any; interface Window extends Record<string, any> {
nonEnumerableValue: string;
} }
} }

View File

@ -14,7 +14,7 @@ export function setCurrentRunningSandboxProxy(proxy: WindowProxy | null) {
currentRunningSandboxProxy = proxy; currentRunningSandboxProxy = proxy;
} }
const functionBoundedValueMap = new WeakMap<Function, Function>(); const functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>();
export function getTargetValue(target: any, value: any): any { export function getTargetValue(target: any, value: any): any {
const cachedBoundFunction = functionBoundedValueMap.get(value); const cachedBoundFunction = functionBoundedValueMap.get(value);
if (cachedBoundFunction) { if (cachedBoundFunction) {

View File

@ -2,7 +2,7 @@
* @author Kuitos * @author Kuitos
* @since 2019-04-11 * @since 2019-04-11
*/ */
import { Freer, Rebuilder, SandBox } from '../interfaces'; import type { Freer, Rebuilder, SandBox } from '../interfaces';
import LegacySandbox from './legacy/sandbox'; import LegacySandbox from './legacy/sandbox';
import { patchAtBootstrapping, patchAtMounting } from './patchers'; import { patchAtBootstrapping, patchAtMounting } from './patchers';
import ProxySandbox from './proxySandbox'; import ProxySandbox from './proxySandbox';

View File

@ -2,10 +2,11 @@
* @author Kuitos * @author Kuitos
* @since 2019-04-11 * @since 2019-04-11
*/ */
import { SandBox, SandBoxType } from '../../interfaces'; import type { ObjectType, SandBox } from '../../interfaces';
import { SandBoxType } from '../../interfaces';
import { getTargetValue } from '../common'; import { getTargetValue } from '../common';
function isPropConfigurable(target: object, prop: PropertyKey) { function isPropConfigurable(target: ObjectType, prop: PropertyKey) {
const descriptor = Object.getOwnPropertyDescriptor(target, prop); const descriptor = Object.getOwnPropertyDescriptor(target, prop);
return descriptor ? descriptor.configurable : true; return descriptor ? descriptor.configurable : true;
} }
@ -72,13 +73,12 @@ export default class SingularProxySandbox implements SandBox {
this.type = SandBoxType.LegacyProxy; this.type = SandBoxType.LegacyProxy;
const { addedPropsMapInSandbox, modifiedPropsOriginalValueMapInSandbox, currentUpdatedPropsValueMap } = this; const { addedPropsMapInSandbox, modifiedPropsOriginalValueMapInSandbox, currentUpdatedPropsValueMap } = this;
const self = this;
const rawWindow = window; const rawWindow = window;
const fakeWindow = Object.create(null) as Window; const fakeWindow = Object.create(null) as Window;
const proxy = new Proxy(fakeWindow, { const proxy = new Proxy(fakeWindow, {
set(_: Window, p: PropertyKey, value: any): boolean { set: (_: Window, p: PropertyKey, value: any): boolean => {
if (self.sandboxRunning) { if (this.sandboxRunning) {
if (!rawWindow.hasOwnProperty(p)) { if (!rawWindow.hasOwnProperty(p)) {
addedPropsMapInSandbox.set(p, value); addedPropsMapInSandbox.set(p, value);
} else if (!modifiedPropsOriginalValueMapInSandbox.has(p)) { } else if (!modifiedPropsOriginalValueMapInSandbox.has(p)) {
@ -92,7 +92,7 @@ export default class SingularProxySandbox implements SandBox {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
(rawWindow as any)[p] = value; (rawWindow as any)[p] = value;
self.latestSetProp = p; this.latestSetProp = p;
return true; return true;
} }

View File

@ -4,7 +4,7 @@
*/ */
import { checkActivityFunctions } from 'single-spa'; import { checkActivityFunctions } from 'single-spa';
import { Freer } from '../../../interfaces'; import type { Freer } from '../../../interfaces';
import { patchHTMLDynamicAppendPrototypeFunctions, rebuildCSSRules, recordStyledComponentsCSSRules } from './common'; import { patchHTMLDynamicAppendPrototypeFunctions, rebuildCSSRules, recordStyledComponentsCSSRules } from './common';
let bootstrappingPatchCount = 0; let bootstrappingPatchCount = 0;

View File

@ -3,10 +3,10 @@
* @since 2020-10-13 * @since 2020-10-13
*/ */
import { Freer } from '../../../interfaces'; import type { Freer } from '../../../interfaces';
import { getCurrentRunningSandboxProxy } from '../../common'; import { getCurrentRunningSandboxProxy } from '../../common';
import type { ContainerConfig } from './common';
import { import {
ContainerConfig,
isHijackingTag, isHijackingTag,
patchHTMLDynamicAppendPrototypeFunctions, patchHTMLDynamicAppendPrototypeFunctions,
rawHeadAppendChild, rawHeadAppendChild,

View File

@ -3,7 +3,8 @@
* @since 2019-04-11 * @since 2019-04-11
*/ */
import { Freer, SandBox, SandBoxType } from '../../interfaces'; import type { Freer, SandBox } from '../../interfaces';
import { SandBoxType } from '../../interfaces';
import * as css from './css'; import * as css from './css';
import { patchLooseSandbox, patchStrictSandbox } from './dynamicAppend'; import { patchLooseSandbox, patchStrictSandbox } from './dynamicAppend';
import patchHistoryListener from './historyListener'; import patchHistoryListener from './historyListener';
@ -15,7 +16,7 @@ export function patchAtMounting(
elementGetter: () => HTMLElement | ShadowRoot, elementGetter: () => HTMLElement | ShadowRoot,
sandbox: SandBox, sandbox: SandBox,
scopedCSS: boolean, scopedCSS: boolean,
excludeAssetFilter?: Function, excludeAssetFilter?: CallableFunction,
): Freer[] { ): Freer[] {
const basePatchers = [ const basePatchers = [
() => patchInterval(sandbox.proxy), () => patchInterval(sandbox.proxy),
@ -46,7 +47,7 @@ export function patchAtBootstrapping(
elementGetter: () => HTMLElement | ShadowRoot, elementGetter: () => HTMLElement | ShadowRoot,
sandbox: SandBox, sandbox: SandBox,
scopedCSS: boolean, scopedCSS: boolean,
excludeAssetFilter?: Function, excludeAssetFilter?: CallableFunction,
): Freer[] { ): Freer[] {
const patchersInSandbox = { const patchersInSandbox = {
[SandBoxType.LegacyProxy]: [ [SandBoxType.LegacyProxy]: [

View File

@ -17,7 +17,7 @@ export default function patch(global: Window) {
return rawWindowClearInterval(intervalId); return rawWindowClearInterval(intervalId);
}; };
global.setInterval = (handler: Function, timeout?: number, ...args: any[]) => { global.setInterval = (handler: CallableFunction, timeout?: number, ...args: any[]) => {
const intervalId = rawWindowInterval(handler, timeout, ...args); const intervalId = rawWindowInterval(handler, timeout, ...args);
intervals = [...intervals, intervalId]; intervals = [...intervals, intervalId];
return intervalId; return intervalId;

View File

@ -3,7 +3,8 @@
* @author Kuitos * @author Kuitos
* @since 2020-3-31 * @since 2020-3-31
*/ */
import { SandBox, SandBoxType } from '../interfaces'; import type { SandBox } from '../interfaces';
import { SandBoxType } from '../interfaces';
import { nextTick } from '../utils'; import { nextTick } from '../utils';
import { getTargetValue, setCurrentRunningSandboxProxy } from './common'; import { getTargetValue, setCurrentRunningSandboxProxy } from './common';
@ -167,7 +168,6 @@ export default class ProxySandbox implements SandBox {
this.type = SandBoxType.Proxy; this.type = SandBoxType.Proxy;
const { updatedValueSet } = this; const { updatedValueSet } = this;
const self = this;
const rawWindow = window; const rawWindow = window;
const { fakeWindow, propertiesWithGetter } = createFakeWindow(rawWindow); const { fakeWindow, propertiesWithGetter } = createFakeWindow(rawWindow);
@ -175,8 +175,8 @@ export default class ProxySandbox implements SandBox {
const hasOwnProperty = (key: PropertyKey) => fakeWindow.hasOwnProperty(key) || rawWindow.hasOwnProperty(key); const hasOwnProperty = (key: PropertyKey) => fakeWindow.hasOwnProperty(key) || rawWindow.hasOwnProperty(key);
const proxy = new Proxy(fakeWindow, { const proxy = new Proxy(fakeWindow, {
set(target: FakeWindow, p: PropertyKey, value: any): boolean { set: (target: FakeWindow, p: PropertyKey, value: any): boolean => {
if (self.sandboxRunning) { if (this.sandboxRunning) {
// We must kept its description while the property existed in rawWindow before // We must kept its description while the property existed in rawWindow before
if (!target.hasOwnProperty(p) && rawWindow.hasOwnProperty(p)) { if (!target.hasOwnProperty(p) && rawWindow.hasOwnProperty(p)) {
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, p); const descriptor = Object.getOwnPropertyDescriptor(rawWindow, p);
@ -201,7 +201,7 @@ export default class ProxySandbox implements SandBox {
updatedValueSet.add(p); updatedValueSet.add(p);
self.latestSetProp = p; this.latestSetProp = p;
return true; return true;
} }

View File

@ -2,9 +2,10 @@
* @author Hydrogen * @author Hydrogen
* @since 2020-3-8 * @since 2020-3-8
*/ */
import { SandBox, SandBoxType } from '../interfaces'; import type { ObjectType, SandBox } from '../interfaces';
import { SandBoxType } from '../interfaces';
function iter(obj: object, callbackFn: (prop: any) => void) { function iter(obj: ObjectType, callbackFn: (prop: any) => void) {
// eslint-disable-next-line guard-for-in, no-restricted-syntax // eslint-disable-next-line guard-for-in, no-restricted-syntax
for (const prop in obj) { for (const prop in obj) {
if (obj.hasOwnProperty(prop)) { if (obj.hasOwnProperty(prop)) {

View File

@ -4,7 +4,7 @@
*/ */
import { isFunction, snakeCase } from 'lodash'; import { isFunction, snakeCase } from 'lodash';
import { FrameworkConfiguration } from './interfaces'; import type { FrameworkConfiguration } from './interfaces';
export function toArray<T>(array: T | T[]): T[] { export function toArray<T>(array: T | T[]): T[] {
return Array.isArray(array) ? array : [array]; return Array.isArray(array) ? array : [array];
@ -22,7 +22,7 @@ export function nextTick(cb: () => void): void {
Promise.resolve().then(cb); Promise.resolve().then(cb);
} }
const constructableMap = new WeakMap<Function, boolean>(); const constructableMap = new WeakMap<any | FunctionConstructor, boolean>();
export function isConstructable(fn: () => any | FunctionConstructor) { export function isConstructable(fn: () => any | FunctionConstructor) {
if (constructableMap.has(fn)) { if (constructableMap.has(fn)) {
return constructableMap.get(fn); return constructableMap.get(fn);