/**
* Copyright (c) Cisco Systems, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
/** This mixin check thay each other mixins in the prototype chain are not applied more than once to the final component class.
* Example:
* import { DedupeMixin, wasApplied } from "./DedupeMixin";
*
* const Mixin = (superclass) => {
* if (wasApplied(Mixin, superclass)) { <---- Check that mixin already applied to superclass.
return superclass;
}
class MixinClass extends superclass {
// MixinClass implementation
}
DedupeMixin(Mixin, MixinClass); <---- If mixin not applied to superclass, save it in WeakMap to check prototype chain next time.
return MixinClass;
* }
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type AnyFunction = (...input: any[]) => A;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type AnyConstructor = new (...input: any[]) => A;
const appliedMixins = new WeakMap();
export const wasApplied = (mixin: AnyFunction, superClass: AnyConstructor) => {
const entries = appliedMixins.get(mixin);
let proto = superClass;
const chain = [];
while (proto) {
chain.push(proto);
proto = Object.getPrototypeOf(proto);
}
return entries ? chain.reduce((res: boolean, protoClass) => res || entries.has(protoClass), false) : false;
};
export const DedupeMixin = (mixin: AnyFunction, superClass: AnyConstructor) => {
let entries = appliedMixins.get(mixin);
if (!entries) {
entries = new WeakSet();
appliedMixins.set(mixin, entries);
}
entries.add(superClass);
};