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

excaliburjs / Excalibur / 11772012724

11 Nov 2024 04:15AM UTC coverage: 90.087% (-0.04%) from 90.128%
11772012724

push

github

eonarheim
feat: Add traditional lerp functions for ease of use

5860 of 7464 branches covered (78.51%)

0 of 12 new or added lines in 1 file covered. (0.0%)

12841 of 14254 relevant lines covered (90.09%)

25220.89 hits per line

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

62.3
/src/engine/Util/Detector.ts
1
import { Logger } from './Log';
2
/**
3
 * This is the list of features that will be used to log the supported
4
 * features to the console when Detector.logBrowserFeatures() is called.
5
 */
6

7
const REPORTED_FEATURES: { [key: string]: string } = {
1✔
8
  webgl: 'WebGL',
9
  webaudio: 'WebAudio',
10
  gamepadapi: 'Gamepad API'
11
};
12

13
/**
14
 * Interface for detected browser features matrix
15
 */
16
export interface DetectedFeatures {
17
  readonly canvas: boolean;
18
  readonly arraybuffer: boolean;
19
  readonly dataurl: boolean;
20
  readonly objecturl: boolean;
21
  readonly rgba: boolean;
22
  readonly webaudio: boolean;
23
  readonly webgl: boolean;
24
  readonly gamepadapi: boolean;
25
}
26

27
interface CriticalTests {
28
  canvasSupport(): boolean;
29
  arrayBufferSupport(): boolean;
30
  dataUrlSupport(): boolean;
31
  objectUrlSupport(): boolean;
32
  rgbaSupport(): boolean;
33
}
34

35
interface WarningTests {
36
  webAudioSupport(): boolean;
37
  webglSupport(): boolean;
38
}
39

40
/**
41
 * Excalibur internal feature detection helper class
42
 */
43
export class Detector {
44
  private _features: DetectedFeatures = null;
690✔
45

46
  public failedTests: string[] = [];
690✔
47

48
  public constructor() {
49
    this._features = this._loadBrowserFeatures();
690✔
50
  }
51

52
  /**
53
   * Returns a map of currently supported browser features. This method
54
   * treats the features as a singleton and will only calculate feature
55
   * support if it has not previously been done.
56
   */
57
  public getBrowserFeatures(): DetectedFeatures {
58
    if (this._features === null) {
×
59
      this._features = this._loadBrowserFeatures();
×
60
    }
61
    return this._features;
×
62
  }
63

64
  /**
65
   * Report on non-critical browser support for debugging purposes.
66
   * Use native browser console colors for visibility.
67
   */
68
  public logBrowserFeatures(): void {
69
    let msg = '%cSUPPORTED BROWSER FEATURES\n==========================%c\n';
×
70
    const args = ['font-weight: bold; color: navy', 'font-weight: normal; color: inherit'];
×
71

72
    const supported: any = this.getBrowserFeatures();
×
73
    for (const feature of Object.keys(REPORTED_FEATURES)) {
×
74
      if (supported[feature]) {
×
75
        msg += '(%c\u2713%c)'; // (✓)
×
76
        args.push('font-weight: bold; color: green');
×
77
        args.push('font-weight: normal; color: inherit');
×
78
      } else {
79
        msg += '(%c\u2717%c)'; // (✗)
×
80
        args.push('font-weight: bold; color: red');
×
81
        args.push('font-weight: normal; color: inherit');
×
82
      }
83

84
      msg += ' ' + REPORTED_FEATURES[feature] + '\n';
×
85
    }
86

87
    args.unshift(msg);
×
88
    // eslint-disable-next-line no-console
89
    console.log.apply(console, args);
×
90
  }
91

92
  /**
93
   * Executes several IIFE's to get a constant reference to supported
94
   * features within the current execution context.
95
   */
96
  private _loadBrowserFeatures(): DetectedFeatures {
97
    return {
690✔
98
      // IIFE to check canvas support
99
      canvas: (() => {
100
        return this._criticalTests.canvasSupport();
690✔
101
      })(),
102

103
      // IIFE to check arraybuffer support
104
      arraybuffer: (() => {
105
        return this._criticalTests.arrayBufferSupport();
690✔
106
      })(),
107

108
      // IIFE to check dataurl support
109
      dataurl: (() => {
110
        return this._criticalTests.dataUrlSupport();
690✔
111
      })(),
112

113
      // IIFE to check objecturl support
114
      objecturl: (() => {
115
        return this._criticalTests.objectUrlSupport();
690✔
116
      })(),
117

118
      // IIFE to check rgba support
119
      rgba: (() => {
120
        return this._criticalTests.rgbaSupport();
690✔
121
      })(),
122

123
      // IIFE to check webaudio support
124
      webaudio: (() => {
125
        return this._warningTest.webAudioSupport();
690✔
126
      })(),
127

128
      // IIFE to check webgl support
129
      webgl: (() => {
130
        return this._warningTest.webglSupport();
690✔
131
      })(),
132

133
      // IIFE to check gamepadapi support
134
      gamepadapi: (() => {
135
        return !!(<any>navigator).getGamepads;
690✔
136
      })()
137
    };
138
  }
139

140
  // critical browser features required for ex to run
141
  private _criticalTests: CriticalTests = {
690✔
142
    // Test canvas/2d context support
143
    canvasSupport: function () {
144
      const elem = document.createElement('canvas');
696✔
145
      return !!(elem.getContext && elem.getContext('2d'));
696✔
146
    },
147

148
    // Test array buffer support ex uses for downloading binary data
149
    arrayBufferSupport: function () {
150
      const xhr = new XMLHttpRequest();
696✔
151
      xhr.open('GET', '/');
696✔
152
      try {
696✔
153
        xhr.responseType = 'arraybuffer';
696✔
154
      } catch (e) {
155
        return false;
×
156
      }
157
      return xhr.responseType === 'arraybuffer';
696✔
158
    },
159

160
    // Test data urls ex uses for sprites
161
    dataUrlSupport: function () {
162
      const canvas = document.createElement('canvas');
696✔
163
      return canvas.toDataURL('image/png').indexOf('data:image/png') === 0;
696✔
164
    },
165

166
    // Test object url support for loading
167
    objectUrlSupport: function () {
168
      return 'URL' in window && 'revokeObjectURL' in URL && 'createObjectURL' in URL;
696✔
169
    },
170

171
    // RGBA support for colors
172
    rgbaSupport: function () {
173
      const style = document.createElement('a').style;
696✔
174
      style.cssText = 'background-color:rgba(150,255,150,.5)';
696✔
175
      return ('' + style.backgroundColor).indexOf('rgba') > -1;
696✔
176
    }
177
  };
178

179
  // warnings excalibur performance will be degraded
180
  private _warningTest: WarningTests = {
690✔
181
    webAudioSupport: function () {
182
      return !!(
696✔
183
        (<any>window).AudioContext ||
696!
184
        (<any>window).webkitAudioContext ||
185
        (<any>window).mozAudioContext ||
186
        (<any>window).msAudioContext ||
187
        (<any>window).oAudioContext
188
      );
189
    },
190
    webglSupport: function () {
191
      const elem = document.createElement('canvas');
696✔
192
      return !!(elem.getContext && elem.getContext('webgl'));
696✔
193
    }
194
  };
195

196
  public test(): boolean {
197
    // Critical test will for ex not to run
198
    let failedCritical = false;
6✔
199
    for (const test in this._criticalTests) {
6✔
200
      if (!this._criticalTests[<keyof CriticalTests>test].call(this)) {
30!
201
        this.failedTests.push(test);
×
202
        Logger.getInstance().error('Critical browser feature missing, Excalibur requires:', test);
×
203
        failedCritical = true;
×
204
      }
205
    }
206
    if (failedCritical) {
6!
207
      return false;
×
208
    }
209

210
    // Warning tests do not for ex to return false to compatibility
211
    for (const warning in this._warningTest) {
6✔
212
      if (!this._warningTest[<keyof WarningTests>warning]()) {
12!
213
        Logger.getInstance().warn('Warning browser feature missing, Excalibur will have reduced performance:', warning);
×
214
      }
215
    }
216

217
    return true;
6✔
218
  }
219
}
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