Skip to content

Commit

Permalink
Merge pull request #69 from Battosuai/fix/memory-leak-mixin-tracking
Browse files Browse the repository at this point in the history
fix: weakmap in mixing tracking
  • Loading branch information
tannerntannern committed Feb 20, 2024
2 parents d7d4371 + acd28db commit 2bbed01
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions src/mixin-tracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import { protoChain } from './util';
import { Class } from './types';

// Keeps track of constituent classes for every mixin class created by ts-mixer.
const mixins = new Map<any, Function[]>();
const mixins = new WeakMap<any, Function[]>();

export const getMixinsForClass = (clazz: Class) =>
mixins.get(clazz);
export const getMixinsForClass = (clazz: Class) => mixins.get(clazz);

export const registerMixins = (mixedClass: any, constituents: Function[]) =>
mixins.set(mixedClass, constituents);

export const hasMixin = <M>(instance: any, mixin: abstract new (...args) => M): instance is M => {
if (instance instanceof mixin)
return true;
export const hasMixin = <M>(
instance: any,
mixin: abstract new (...args) => M
): instance is M => {
if (instance instanceof mixin) return true;

const constructor = instance.constructor;

Expand All @@ -23,14 +24,18 @@ export const hasMixin = <M>(instance: any, mixin: abstract new (...args) => M):
while (frontier.size > 0) {
// check if the frontier has the mixin we're looking for. if not, we can say we visited every item in the frontier
if (frontier.has(mixin)) return true;
frontier.forEach(item => visited.add(item));
frontier.forEach((item) => visited.add(item));

// build a new frontier based on the associated mixin classes and prototype chains of each frontier item
const newFrontier = new Set<Function>();
frontier.forEach(item => {
const itemConstituents = mixins.get(item) ?? protoChain(item.prototype).map(proto => proto.constructor).filter(item => item !== null);
frontier.forEach((item) => {
const itemConstituents =
mixins.get(item) ??
protoChain(item.prototype)
.map((proto) => proto.constructor)
.filter((item) => item !== null);
if (itemConstituents)
itemConstituents.forEach(constituent => {
itemConstituents.forEach((constituent) => {
if (!visited.has(constituent) && !frontier.has(constituent))
newFrontier.add(constituent);
});
Expand Down

0 comments on commit 2bbed01

Please sign in to comment.