• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excaliburjs / Excalibur / 18842529456

27 Oct 2025 01:24PM UTC coverage: 88.6% (-0.006%) from 88.606%
18842529456

push

github

web-flow
chore(deps-dev): bump tar-fs from 3.1.0 to 3.1.1 (#3521)

Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 3.1.0 to 3.1.1.
- [Commits](https://github.com/mafintosh/tar-fs/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-version: 3.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

5252 of 7154 branches covered (73.41%)

14425 of 16281 relevant lines covered (88.6%)

24353.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/src/engine/GarbageCollector.ts
1
export interface GarbageCollectionOptions {
2
  /**
3
   * Textures that aren't drawn after a certain number of milliseconds are unloaded from the GPU
4
   * Default 60_000 ms
5
   */
6
  textureCollectInterval?: number; // default 60_000 ms
7
  // TODO future work to integrate the font and text configuration, refactor existing collection mechanism
8
  // /**
9
  //  * Font pre-renders that aren't drawn after a certain number of milliseconds are unloaded from the GPU
10
  //  * Default 60_000 ms
11
  //  */
12
  // fontCollectInterval: number; // default 60_000 ms
13
  // /**
14
  //  * Text measurements that aren't used after a certain number of milliseconds are unloaded from the GPU
15
  //  * Default 60_000 ms
16
  //  */
17
  // textMeasurementCollectInterval: number; // default 60_000 ms
18
}
19

20
export const DefaultGarbageCollectionOptions: GarbageCollectionOptions = {
248✔
21
  textureCollectInterval: 60_000
22
  // TODO future work to integrate the font and text configuration, refactor existing collection mechanism
23
  // fontCollectInterval: 60_000,
24
  // textMeasurementCollectInterval: 60_000,
25
};
26

27
export interface GarbageCollectorOptions {
28
  /**
29
   * Returns a timestamp in milliseconds representing now
30
   */
31
  getTimestamp: () => number;
32
}
33

34
export class GarbageCollector {
35
  private _collectHandle: number;
36
  private _running = false;
740✔
37
  private _collectionMap = new Map<any, [type: string, time: number]>();
740✔
38
  private _collectors = new Map<string, [(resource: any) => boolean, interval: number]>();
740✔
39

40
  constructor(public options: GarbageCollectorOptions) {}
740✔
41

42
  /**
43
   *
44
   * @param type Resource type
45
   * @param timeoutInterval If resource type exceeds interval in milliseconds collect() is called
46
   * @param collect Collection implementation, returns true if collected
47
   */
48
  registerCollector(type: string, timeoutInterval: number, collect: (resource: any) => boolean) {
49
    this._collectors.set(type, [collect, timeoutInterval]);
737✔
50
  }
51

52
  /**
53
   * Add a resource to be tracked for collection
54
   * @param type
55
   * @param resource
56
   */
57
  addCollectableResource(type: string, resource: any) {
58
    this._collectionMap.set(resource, [type, this.options.getTimestamp()]);
166✔
59
  }
60

61
  /**
62
   * Update the resource last used timestamp preventing collection
63
   * @param resource
64
   */
65
  touch(resource: any) {
66
    const collectionData = this._collectionMap.get(resource);
1,751✔
67
    if (collectionData) {
1,751!
68
      this._collectionMap.set(resource, [collectionData[0], this.options.getTimestamp()]);
1,751✔
69
    }
70
  }
71

72
  /**
73
   * Runs the collection loop to cleanup any stale resources given the registered collect handlers
74
   */
75
  public collectStaleResources = (deadline?: IdleDeadline) => {
740✔
76
    if (!this._running) {
922!
77
      return;
×
78
    }
79
    for (const [type, [collector, timeoutInterval]] of this._collectors.entries()) {
922✔
80
      const now = this.options.getTimestamp();
903✔
81
      for (const [resource, [resourceType, time]] of this._collectionMap.entries()) {
903✔
82
        if (type !== resourceType || time + timeoutInterval >= now) {
303✔
83
          continue;
301✔
84
        }
85

86
        const collected = collector(resource);
2✔
87
        if (collected) {
2!
88
          this._collectionMap.delete(resource);
2✔
89
        }
90
      }
91
    }
92

93
    this._collectHandle = requestIdleCallback(this.collectStaleResources);
922✔
94
  };
95

96
  /**
97
   * Force collect all resources, useful for shutting down a game
98
   * or if you know that you will not use anything you've allocated before now
99
   */
100
  public forceCollectAll() {
101
    for (const [_, [collector]] of this._collectors.entries()) {
735✔
102
      for (const [resource] of this._collectionMap.entries()) {
734✔
103
        const collected = collector(resource);
164✔
104
        if (collected) {
164!
105
          this._collectionMap.delete(resource);
164✔
106
        }
107
      }
108
    }
109
  }
110

111
  running(): boolean {
112
    return this._running;
×
113
  }
114

115
  /**
116
   * Starts the garbage collection loop
117
   */
118
  start() {
119
    this._running = true;
573✔
120
    this.collectStaleResources();
573✔
121
  }
122

123
  /**
124
   * Stops the garbage collection loop
125
   */
126
  stop() {
127
    this._running = false;
579✔
128
    cancelIdleCallback(this._collectHandle);
579✔
129
  }
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc