@codexo/exojs 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,75 @@ All notable changes to ExoJS are documented in this file.
4
4
 
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.6.4] - 2026-05-02
8
+
9
+ > **Heads-up — breaking change despite the patch number.** Reshapes
10
+ > the capabilities API one version after it was introduced. Pre-1.0
11
+ > SemVer permits breaking changes within the 0.x.y line; we kept the
12
+ > minor digit unchanged because the previous shape only existed for
13
+ > a single release (0.6.3) and almost no one will have pinned to it.
14
+
15
+ 0.6.3 shipped a sync-only `capabilities` object plus an `isSupported`
16
+ helper; both are gone. The replacement is a `Capabilities` class with
17
+ a lazy-cached `static get ready` Promise — async-aware (real WebGPU
18
+ adapter check, not just API surface), flat-property, OOP-flavored to
19
+ match the rest of ExoJS.
20
+
21
+ ### Breaking
22
+
23
+ - **`capabilities` (lowercase const) and `isSupported` are removed.**
24
+ Replace with `await Capabilities.ready`. Properties on the resolved
25
+ instance carry the same information at richer fidelity:
26
+ - `capabilities.touch` (`boolean`) → `caps.touch` (`boolean`) plus
27
+ new `caps.maxTouchPoints` (`number`).
28
+ - `capabilities.webgpu` (`boolean`, API-surface only) →
29
+ `caps.webgpu` (`boolean`, same API-surface meaning) plus new
30
+ `caps.webgpuAdapter` (`GPUAdapter | null`, the actual adapter
31
+ request result), `caps.webgpuVendor`, `caps.webgpuArchitecture`.
32
+ - `capabilities.audio` (`boolean`) → `caps.audio` (`boolean`).
33
+ - All other booleans (`pointer`, `keyboard`, `gamepad`,
34
+ `fullscreen`, `vibration`, `offscreenCanvas`, `webWorkers`,
35
+ `devicePixelRatio`, `webgl2`) carry over with identical names.
36
+ - **`CapabilityName` type is removed.** It existed only to type
37
+ `isSupported`'s parameter; with the function gone the union has no
38
+ consumer.
39
+
40
+ ### Added
41
+
42
+ - **`Capabilities` class** with lazy-cached static `ready` Promise.
43
+ First read fires the probes (sync ones immediate, the WebGPU
44
+ adapter check async); every subsequent read returns the same
45
+ Promise. The resolved instance is frozen.
46
+ - **`Application.capabilities`** accessor returns the same instance
47
+ after `await app.start(...)` resolves; reading before start throws.
48
+ Application's start now overlaps capability detection with backend
49
+ init via `Promise.all`-style parallelism — no extra startup
50
+ latency.
51
+ - **Real WebGPU adapter check** as part of detection: `webgpuAdapter`
52
+ is non-null only if `navigator.gpu.requestAdapter()` succeeded.
53
+ Solves the "API surface present but adapter not available" false
54
+ positive that the 0.6.3 sync `capabilities.webgpu` couldn't
55
+ distinguish.
56
+
57
+ ### Migration
58
+
59
+ ```ts
60
+ // Before (0.6.3)
61
+ import { capabilities, isSupported } from '@codexo/exojs';
62
+ if (capabilities.webgpu) startWebGpu(); // false positives possible
63
+ if (isSupported('touch')) showTouchUi();
64
+
65
+ // After (0.6.4)
66
+ import { Capabilities } from '@codexo/exojs';
67
+ const caps = await Capabilities.ready;
68
+ if (caps.webgpuAdapter) startWebGpu(); // strict adapter check
69
+ if (caps.touch) showTouchUi();
70
+
71
+ // Or via Application after start:
72
+ await app.start(scene);
73
+ if (app.capabilities.touch) showTouchUi();
74
+ ```
75
+
7
76
  ## [0.6.3] - 2026-05-02
8
77
 
9
78
  Adds the `capabilities` feature-detection API. Pure addition — no
@@ -1,3 +1,4 @@
1
+ import { Capabilities } from './capabilities';
1
2
  import { SceneManager } from './SceneManager';
2
3
  import { InputManager } from '@/input/InputManager';
3
4
  import { Loader } from '@/resources/Loader';
@@ -57,6 +58,7 @@ export declare class Application {
57
58
  private _frameRequest;
58
59
  private _backendType;
59
60
  private _backend;
61
+ private _capabilities;
60
62
  constructor(appSettings?: Partial<ApplicationOptions>);
61
63
  get status(): ApplicationStatus;
62
64
  get startupTime(): Time;
@@ -64,6 +66,12 @@ export declare class Application {
64
66
  get frameTime(): Time;
65
67
  get frameCount(): number;
66
68
  get backend(): RenderBackend;
69
+ /**
70
+ * Resolved capabilities for the host browser. Available after
71
+ * {@link Application.start} resolves; reading before that throws.
72
+ * For pre-start access use {@link Capabilities.ready} directly.
73
+ */
74
+ get capabilities(): Capabilities;
67
75
  start(scene: Scene): Promise<this>;
68
76
  update(): this;
69
77
  stop(): this;
@@ -1,3 +1,4 @@
1
+ import { Capabilities } from './capabilities.js';
1
2
  import { Clock } from './Clock.js';
2
3
  import { SceneManager } from './SceneManager.js';
3
4
  import { WebGl2Backend } from '../rendering/webgl2/WebGl2Backend.js';
@@ -59,6 +60,7 @@ class Application {
59
60
  _frameRequest = 0;
60
61
  _backendType;
61
62
  _backend;
63
+ _capabilities = null;
62
64
  constructor(appSettings) {
63
65
  this.options = {
64
66
  canvas: appSettings?.canvas ?? createDefaultCanvas(),
@@ -100,11 +102,26 @@ class Application {
100
102
  get backend() {
101
103
  return this._backend;
102
104
  }
105
+ /**
106
+ * Resolved capabilities for the host browser. Available after
107
+ * {@link Application.start} resolves; reading before that throws.
108
+ * For pre-start access use {@link Capabilities.ready} directly.
109
+ */
110
+ get capabilities() {
111
+ if (this._capabilities === null) {
112
+ throw new Error('Application.capabilities is unavailable before start() resolves. Use `await Capabilities.ready` for pre-start checks.');
113
+ }
114
+ return this._capabilities;
115
+ }
103
116
  async start(scene) {
104
117
  if (this._status === ApplicationStatus.Stopped) {
105
118
  this._status = ApplicationStatus.Loading;
119
+ // Kick off capability detection in parallel with renderer init —
120
+ // both are mostly-async startup work, no point serializing them.
121
+ const capabilitiesPromise = Capabilities.ready;
106
122
  try {
107
123
  await this.initializeRenderManager();
124
+ this._capabilities = await capabilitiesPromise;
108
125
  await this.sceneManager.setScene(scene);
109
126
  this._frameRequest = requestAnimationFrame(this._updateHandler);
110
127
  this._frameClock.restart();
@@ -1 +1 @@
1
- {"version":3,"file":"Application.js","sources":["../../../../src/core/Application.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Application.js","sources":["../../../../src/core/Application.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,37 +1,38 @@
1
- interface CapabilitiesShape {
2
- /** A real WebGL2 context can be created on a probe canvas. */
1
+ export declare class Capabilities {
2
+ private static _readyPromise;
3
+ /**
4
+ * Lazy-cached Promise that resolves to a frozen Capabilities instance.
5
+ *
6
+ * The first read kicks off the async probes (currently just the WebGPU
7
+ * adapter request); every subsequent read returns the same Promise.
8
+ * Concurrent callers share the in-flight detection — no double work.
9
+ *
10
+ * Early-warmup pattern for callers who want to overlap detection with
11
+ * other startup work:
12
+ *
13
+ * ```ts
14
+ * void Capabilities.ready; // fire-and-forget; starts probes now
15
+ * // ... unrelated bootstrap ...
16
+ * const caps = await Capabilities.ready; // typically already resolved
17
+ * ```
18
+ */
19
+ static get ready(): Promise<Capabilities>;
3
20
  readonly webgl2: boolean;
4
- /** `navigator.gpu` is present. Does NOT guarantee adapter availability. */
5
21
  readonly webgpu: boolean;
6
- /** `AudioContext` (standard or `webkit`-prefixed) is constructable. */
7
- readonly audio: boolean;
8
- /** `PointerEvent` is supported. */
22
+ readonly webgpuAdapter: GPUAdapter | null;
23
+ readonly webgpuVendor: string | null;
24
+ readonly webgpuArchitecture: string | null;
9
25
  readonly pointer: boolean;
10
- /** Touch input is exposed via `ontouchstart` or `maxTouchPoints > 0`. */
11
- readonly touch: boolean;
12
- /** `navigator.getGamepads` is available. */
13
- readonly gamepad: boolean;
14
- /** `KeyboardEvent` is supported. */
15
26
  readonly keyboard: boolean;
16
- /** The Fullscreen API is exposed on the document element. */
27
+ readonly gamepad: boolean;
28
+ readonly touch: boolean;
29
+ readonly maxTouchPoints: number;
30
+ readonly audio: boolean;
17
31
  readonly fullscreen: boolean;
18
- /** `navigator.vibrate` is available. */
19
32
  readonly vibration: boolean;
20
- /** `OffscreenCanvas` constructor is on the global. */
21
33
  readonly offscreenCanvas: boolean;
34
+ readonly webWorkers: boolean;
35
+ readonly devicePixelRatio: number;
36
+ private constructor();
37
+ private static _detect;
22
38
  }
23
- export type Capabilities = CapabilitiesShape;
24
- export type CapabilityName = keyof CapabilitiesShape;
25
- /**
26
- * Synchronous, one-shot feature-detection results. Computed once at
27
- * module load and frozen. Use either as a property bag (`capabilities.touch`)
28
- * or via {@link isSupported} for typed lookup.
29
- */
30
- export declare const capabilities: Capabilities;
31
- /**
32
- * Typed lookup over {@link capabilities}. Identical to
33
- * `capabilities[name]` but the function form gives clearer call-sites
34
- * when the name is computed.
35
- */
36
- export declare function isSupported(name: CapabilityName): boolean;
37
- export {};
@@ -1,17 +1,99 @@
1
- // Browser feature-detection probes evaluated once at module load. The
2
- // resulting `capabilities` object is a `Readonly<Record<CapabilityName,
3
- // boolean>>` and can be inspected directly or queried via `isSupported`.
1
+ /// <reference types="@webgpu/types" />
2
+ // Browser-environment feature detection. Construction is private; the
3
+ // only public entry is `Capabilities.ready`, a lazy-cached `Promise<Capabilities>`
4
+ // that fires the (mostly) async probes on first access and returns the
5
+ // same Promise for every subsequent call. Once it resolves, the returned
6
+ // instance is frozen — every property is read once and never mutates.
4
7
  //
5
- // All probes are synchronous. Async questions ("can I actually acquire a
6
- // WebGPU adapter?", "can the audio decoder play this OGG file?") are
7
- // outside this module's scope — they're owned by the Application's
8
- // backend selection and the Loader respectively. `capabilities.webgpu`
9
- // returning `true` only guarantees that the browser advertises WebGPU,
10
- // not that an adapter request will succeed.
8
+ // Synchronous callsites should keep the resolved instance in scope (e.g.,
9
+ // `app.capabilities` after `await app.start(...)`); there is no global
10
+ // sync mirror, by design.
11
11
  const hasWindow = typeof window !== 'undefined';
12
12
  const hasDocument = typeof document !== 'undefined';
13
13
  const hasNavigator = typeof navigator !== 'undefined';
14
- const probeWebGl2 = () => {
14
+ class Capabilities {
15
+ static _readyPromise = null;
16
+ /**
17
+ * Lazy-cached Promise that resolves to a frozen Capabilities instance.
18
+ *
19
+ * The first read kicks off the async probes (currently just the WebGPU
20
+ * adapter request); every subsequent read returns the same Promise.
21
+ * Concurrent callers share the in-flight detection — no double work.
22
+ *
23
+ * Early-warmup pattern for callers who want to overlap detection with
24
+ * other startup work:
25
+ *
26
+ * ```ts
27
+ * void Capabilities.ready; // fire-and-forget; starts probes now
28
+ * // ... unrelated bootstrap ...
29
+ * const caps = await Capabilities.ready; // typically already resolved
30
+ * ```
31
+ */
32
+ static get ready() {
33
+ if (Capabilities._readyPromise === null) {
34
+ Capabilities._readyPromise = Capabilities._detect();
35
+ }
36
+ return Capabilities._readyPromise;
37
+ }
38
+ webgl2;
39
+ webgpu;
40
+ webgpuAdapter;
41
+ webgpuVendor;
42
+ webgpuArchitecture;
43
+ pointer;
44
+ keyboard;
45
+ gamepad;
46
+ touch;
47
+ maxTouchPoints;
48
+ audio;
49
+ fullscreen;
50
+ vibration;
51
+ offscreenCanvas;
52
+ webWorkers;
53
+ devicePixelRatio;
54
+ constructor(values) {
55
+ this.webgl2 = values.webgl2;
56
+ this.webgpu = values.webgpu;
57
+ this.webgpuAdapter = values.webgpuAdapter;
58
+ this.webgpuVendor = values.webgpuVendor;
59
+ this.webgpuArchitecture = values.webgpuArchitecture;
60
+ this.pointer = values.pointer;
61
+ this.keyboard = values.keyboard;
62
+ this.gamepad = values.gamepad;
63
+ this.touch = values.touch;
64
+ this.maxTouchPoints = values.maxTouchPoints;
65
+ this.audio = values.audio;
66
+ this.fullscreen = values.fullscreen;
67
+ this.vibration = values.vibration;
68
+ this.offscreenCanvas = values.offscreenCanvas;
69
+ this.webWorkers = values.webWorkers;
70
+ this.devicePixelRatio = values.devicePixelRatio;
71
+ Object.freeze(this);
72
+ }
73
+ static async _detect() {
74
+ const [webgpuAdapter, webgpuInfo] = await probeWebGpu();
75
+ return new Capabilities({
76
+ webgl2: probeWebGl2(),
77
+ webgpu: probeWebGpuApiSurface(),
78
+ webgpuAdapter,
79
+ webgpuVendor: webgpuInfo?.vendor ?? null,
80
+ webgpuArchitecture: webgpuInfo?.architecture ?? null,
81
+ pointer: probePointer(),
82
+ keyboard: probeKeyboard(),
83
+ gamepad: probeGamepad(),
84
+ touch: probeTouchSupported(),
85
+ maxTouchPoints: probeMaxTouchPoints(),
86
+ audio: probeAudio(),
87
+ fullscreen: probeFullscreen(),
88
+ vibration: probeVibration(),
89
+ offscreenCanvas: probeOffscreenCanvas(),
90
+ webWorkers: probeWebWorkers(),
91
+ devicePixelRatio: hasWindow ? window.devicePixelRatio : 1,
92
+ });
93
+ }
94
+ }
95
+ // --- probes ---------------------------------------------------------------
96
+ function probeWebGl2() {
15
97
  if (!hasDocument)
16
98
  return false;
17
99
  try {
@@ -22,75 +104,95 @@ const probeWebGl2 = () => {
22
104
  catch {
23
105
  return false;
24
106
  }
25
- };
26
- const probeWebGpu = () => {
107
+ }
108
+ function probeWebGpuApiSurface() {
27
109
  return hasNavigator && 'gpu' in navigator;
28
- };
29
- const probeAudio = () => {
30
- if (!hasWindow)
31
- return false;
32
- const w = window;
33
- return typeof w.AudioContext !== 'undefined' || typeof w.webkitAudioContext !== 'undefined';
34
- };
35
- const probePointer = () => {
110
+ }
111
+ async function probeWebGpu() {
112
+ if (!probeWebGpuApiSurface())
113
+ return [null, null];
114
+ const gpu = navigator.gpu;
115
+ if (!gpu || typeof gpu.requestAdapter !== 'function')
116
+ return [null, null];
117
+ try {
118
+ const adapter = await gpu.requestAdapter();
119
+ if (!adapter)
120
+ return [null, null];
121
+ // Modern path: GPUAdapter.info is a sync property (Chrome 116+,
122
+ // Safari 18+). Older browsers exposed a deprecated async
123
+ // requestAdapterInfo() instead. Try the modern path first, fall
124
+ // back if needed.
125
+ const adapterAny = adapter;
126
+ if (adapterAny.info) {
127
+ return [adapter, adapterAny.info];
128
+ }
129
+ if (typeof adapterAny.requestAdapterInfo === 'function') {
130
+ try {
131
+ return [adapter, await adapterAny.requestAdapterInfo()];
132
+ }
133
+ catch {
134
+ return [adapter, null];
135
+ }
136
+ }
137
+ return [adapter, null];
138
+ }
139
+ catch {
140
+ return [null, null];
141
+ }
142
+ }
143
+ function probePointer() {
36
144
  return hasWindow && 'PointerEvent' in window;
37
- };
38
- const probeTouch = () => {
145
+ }
146
+ function probeKeyboard() {
147
+ return hasWindow && 'KeyboardEvent' in window;
148
+ }
149
+ function probeGamepad() {
150
+ return hasNavigator && typeof navigator.getGamepads === 'function';
151
+ }
152
+ function probeTouchSupported() {
39
153
  if (!hasWindow)
40
154
  return false;
41
155
  if ('ontouchstart' in window)
42
156
  return true;
43
- if (hasNavigator && typeof navigator.maxTouchPoints === 'number' && navigator.maxTouchPoints > 0)
157
+ if (probeMaxTouchPoints() > 0)
44
158
  return true;
45
159
  return false;
46
- };
47
- const probeGamepad = () => {
48
- return hasNavigator && typeof navigator.getGamepads === 'function';
49
- };
50
- const probeKeyboard = () => {
51
- return hasWindow && 'KeyboardEvent' in window;
52
- };
53
- const probeFullscreen = () => {
160
+ }
161
+ function probeMaxTouchPoints() {
162
+ if (!hasNavigator)
163
+ return 0;
164
+ const points = navigator.maxTouchPoints;
165
+ return typeof points === 'number' ? points : 0;
166
+ }
167
+ function probeAudio() {
168
+ if (!hasWindow)
169
+ return false;
170
+ const w = window;
171
+ return typeof w.AudioContext !== 'undefined' || typeof w.webkitAudioContext !== 'undefined';
172
+ }
173
+ function probeFullscreen() {
54
174
  if (!hasDocument)
55
175
  return false;
56
176
  const el = document.documentElement;
57
177
  return typeof el.requestFullscreen === 'function' || typeof el.webkitRequestFullscreen === 'function';
58
- };
59
- const probeVibration = () => {
178
+ }
179
+ function probeVibration() {
60
180
  return hasNavigator && typeof navigator.vibrate === 'function';
61
- };
62
- const probeOffscreenCanvas = () => {
181
+ }
182
+ function probeOffscreenCanvas() {
63
183
  // The browser global is verbatim `OffscreenCanvas`; eslint's
64
184
  // strict-camelCase rule rejects the property name even though we
65
185
  // can't rename a web standard.
66
186
  // eslint-disable-next-line @typescript-eslint/naming-convention
67
187
  return hasWindow && typeof window.OffscreenCanvas !== 'undefined';
68
- };
69
- /**
70
- * Synchronous, one-shot feature-detection results. Computed once at
71
- * module load and frozen. Use either as a property bag (`capabilities.touch`)
72
- * or via {@link isSupported} for typed lookup.
73
- */
74
- const capabilities = Object.freeze({
75
- webgl2: probeWebGl2(),
76
- webgpu: probeWebGpu(),
77
- audio: probeAudio(),
78
- pointer: probePointer(),
79
- touch: probeTouch(),
80
- gamepad: probeGamepad(),
81
- keyboard: probeKeyboard(),
82
- fullscreen: probeFullscreen(),
83
- vibration: probeVibration(),
84
- offscreenCanvas: probeOffscreenCanvas(),
85
- });
86
- /**
87
- * Typed lookup over {@link capabilities}. Identical to
88
- * `capabilities[name]` but the function form gives clearer call-sites
89
- * when the name is computed.
90
- */
91
- function isSupported(name) {
92
- return capabilities[name];
188
+ }
189
+ function probeWebWorkers() {
190
+ // The browser global is verbatim `Worker`; eslint's strict-camelCase
191
+ // rule rejects the property name even though we can't rename a web
192
+ // standard.
193
+ // eslint-disable-next-line @typescript-eslint/naming-convention
194
+ return hasWindow && typeof window.Worker === 'function';
93
195
  }
94
196
 
95
- export { capabilities, isSupported };
197
+ export { Capabilities };
96
198
  //# sourceMappingURL=capabilities.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.js","sources":["../../../../src/core/capabilities.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capabilities.js","sources":["../../../../src/core/capabilities.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { canvasSourceToDataUrl, emptyArrayBuffer, getCanvasSourceSize, getPreciseTime, getTextureSourceSize, hours, milliseconds, minutes, noop, rand, removeArrayItems, seconds, stopEvent, supportsCodec, supportsEventOptions, supportsIndexedDb, supportsPointerEvents, supportsTouchEvents, supportsWebAudio } from './core/utils.js';
2
2
  export { Application, ApplicationStatus } from './core/Application.js';
3
3
  export { Bounds } from './core/Bounds.js';
4
- export { capabilities, isSupported } from './core/capabilities.js';
4
+ export { Capabilities } from './core/capabilities.js';
5
5
  export { Clock } from './core/Clock.js';
6
6
  export { Color } from './core/Color.js';
7
7
  export { Quadtree } from './core/Quadtree.js';