/** Decorator to support multi-inheritance using mixins */
export function Mixin(baseCtors) {
    return function (derivedCtor) {
        for (const baseCtor of baseCtors) {
            applyMixin(derivedCtor, baseCtor);
        }
    };
}
export function applyMixin(target, mixin, includeConstructor = false) {
    // Figure out the inheritance chain of the mixin
    const inheritanceChain = [mixin];
    while (true) {
        const current = inheritanceChain[0];
        const base = Object.getPrototypeOf(current);
        if (base?.prototype) {
            inheritanceChain.unshift(base);
        }
        else {
            break;
        }
    }
    for (const ctor of inheritanceChain) {
        for (const prop of Object.getOwnPropertyNames(ctor.prototype)) {
            // Do not override the constructor
            if (includeConstructor || prop !== "constructor") {
                Object.defineProperty(target.prototype, prop, Object.getOwnPropertyDescriptor(ctor.prototype, prop)
                    ?? Object.create(null));
            }
        }
    }
}
/**
 * Merges the given base classes into one, so extending from all of them at once is possible.
 * The first one will be included with proper inheritance, the remaining ones are mixed in.
 */
export function AllOf(...BaseClasses) {
    const [First, ...Others] = BaseClasses;
    const ret = class AllOf extends First {
    };
    for (const base of Others) {
        applyMixin(ret, base);
    }
    return ret;
}
/** Tests if base is in the super chain of `constructor` */
export function staticExtends(constructor, base) {
    while (constructor) {
        if (constructor === base)
            return true;
        constructor = Object.getPrototypeOf(constructor);
    }
    return false;
}
//# sourceMappingURL=inheritance.js.map