@flighthq/platform 0.5.0-next.1944.cd6b6e7 → 0.5.1-edge.638.d4dbd4e

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/README.md CHANGED
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/platform`. The `@fli
13
13
  This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
14
14
 
15
15
  - [Flight project](https://github.com/flighthq/flight)
16
- - [Source for @flighthq/platform@0.5.0-next.1944.cd6b6e7](https://github.com/flighthq/flight/tree/cd6b6e71eb472b3a4249830a7743333f019fa7b7/packages/platform)
17
- - [License](https://github.com/flighthq/flight/blob/cd6b6e71eb472b3a4249830a7743333f019fa7b7/LICENSE.md)
16
+ - [Source for @flighthq/platform@0.5.1-edge.638.d4dbd4e](https://github.com/flighthq/flight/tree/d4dbd4e347dc8be10b180c85a766ab50333dcb51/packages/platform)
17
+ - [License](https://github.com/flighthq/flight/blob/d4dbd4e347dc8be10b180c85a766ab50333dcb51/LICENSE.md)
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { explainPlatformBackend, comparePlatformVersions, getPlatformEngine, getPlatformInfo, getPlatformKind, getPlatformName, isPlatformDesktop, isPlatformMobile, isPlatformNative, isPlatformTouch, isPlatformVersionAtLeast, isPlatformWeb, } from './contract';
1
+ export { comparePlatformVersions, getPlatformEngine, getPlatformInfo, getPlatformKind, getPlatformName, getPlatformRuntime, isPlatformDesktop, isPlatformMobile, isPlatformNative, isPlatformTouch, isPlatformVersionAtLeast, isPlatformWeb, } from './contract';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,aAAa,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { explainPlatformBackend, comparePlatformVersions, getPlatformEngine, getPlatformInfo, getPlatformKind, getPlatformName, isPlatformDesktop, isPlatformMobile, isPlatformNative, isPlatformTouch, isPlatformVersionAtLeast, isPlatformWeb, } from './contract';
1
+ export { comparePlatformVersions, getPlatformEngine, getPlatformInfo, getPlatformKind, getPlatformName, getPlatformRuntime, isPlatformDesktop, isPlatformMobile, isPlatformNative, isPlatformTouch, isPlatformVersionAtLeast, isPlatformWeb, } from './contract';
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,aAAa,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,aAAa,GACd,MAAM,YAAY,CAAC"}
@@ -1,23 +1,15 @@
1
- import type { BackendExplanation } from '@flighthq/types/contract';
2
- import type { PlatformBackend, PlatformEngine, PlatformInfo, PlatformKind, PlatformName, PlatformRuntime } from '@flighthq/types/contract';
1
+ import type { HasSystemPlatform, PlatformEngine, PlatformInfo, PlatformKind, PlatformName, PlatformRuntime } from '@flighthq/types/contract';
3
2
  export declare function comparePlatformVersions(a: string, b: string): -1 | 0 | 1;
4
3
  export declare function createPlatformInfo(): PlatformInfo;
5
- export declare function createWebPlatformBackend(): PlatformBackend;
6
- export declare function explainPlatformBackend(): BackendExplanation;
7
- export declare function getPlatformBackend(): PlatformBackend;
8
- export declare function getPlatformEngine(): PlatformEngine;
9
- export declare function getPlatformInfo(out: PlatformInfo): PlatformInfo;
10
- export declare function getPlatformKind(): PlatformKind;
11
- export declare function getPlatformName(): PlatformName;
12
- export declare function getPlatformRuntime(): PlatformRuntime;
13
- export declare function installPlatformHostBackend(backend: PlatformBackend): void;
14
- export declare function isPlatformDesktop(): boolean;
15
- export declare function isPlatformMobile(): boolean;
16
- export declare function isPlatformNative(): boolean;
17
- export declare function isPlatformTouch(): boolean;
18
- export declare function isPlatformVersionAtLeast(minimum: string): boolean;
19
- export declare function isPlatformWeb(): boolean;
20
- export declare function observePlatformHostResult(operation: string, succeeded: boolean): void;
21
- export declare function resetPlatformBackendForTest(): void;
22
- export declare function setPlatformBackend(backend: PlatformBackend | null): void;
4
+ export declare function getPlatformEngine(host: HasSystemPlatform): PlatformEngine;
5
+ export declare function getPlatformInfo(host: HasSystemPlatform, out: PlatformInfo): PlatformInfo;
6
+ export declare function getPlatformKind(host: HasSystemPlatform): PlatformKind;
7
+ export declare function getPlatformName(host: HasSystemPlatform): PlatformName;
8
+ export declare function getPlatformRuntime(host: HasSystemPlatform): PlatformRuntime;
9
+ export declare function isPlatformDesktop(host: HasSystemPlatform): boolean;
10
+ export declare function isPlatformMobile(host: HasSystemPlatform): boolean;
11
+ export declare function isPlatformNative(host: HasSystemPlatform): boolean;
12
+ export declare function isPlatformTouch(host: HasSystemPlatform): boolean;
13
+ export declare function isPlatformVersionAtLeast(host: HasSystemPlatform, minimum: string): boolean;
14
+ export declare function isPlatformWeb(host: HasSystemPlatform): boolean;
23
15
  //# sourceMappingURL=platform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAgBlC,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAcxE;AAGD,wBAAgB,kBAAkB,IAAI,YAAY,CAiBjD;AAID,wBAAgB,wBAAwB,IAAI,eAAe,CAE1D;AAED,wBAAgB,sBAAsB,IAAI,kBAAkB,CAa3D;AAID,wBAAgB,kBAAkB,IAAI,eAAe,CAEpD;AAID,wBAAgB,iBAAiB,IAAI,cAAc,CAElD;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAE/D;AAGD,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAGD,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAID,wBAAgB,kBAAkB,IAAI,eAAe,CAEpD;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAMzE;AAGD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAGD,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAID,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C;AAGD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAKD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAIjE;AAGD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAKrF;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAKlD;AAID,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAExE"}
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAKlC,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAcxE;AAGD,wBAAgB,kBAAkB,IAAI,YAAY,CAiBjD;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,cAAc,CAEzE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,YAAY,GAAG,YAAY,CAExF;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,YAAY,CAErE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,YAAY,CAErE;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,eAAe,CAE3E;AAGD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAElE;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAEjE;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAGjE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAEhE;AAKD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAI1F;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAE9D"}
package/dist/platform.js CHANGED
@@ -1,4 +1,3 @@
1
- import { detectEndianness, parseUserAgentArch, parseUserAgentEngine, parseUserAgentEngineVersion, parseUserAgentKind, parseUserAgentName, parseUserAgentPointerWidth, parseUserAgentRuntime, parseUserAgentVersion, } from '@flighthq/useragent/contract';
2
1
  // Compares two dotted version strings numerically, segment by segment. Returns -1, 0, or 1.
3
2
  // Non-numeric trailing segments are ignored; '' sorts lowest. '' compared with '' returns 0.
4
3
  // Example: comparePlatformVersions('10.15.7', '10.15.6') === 1.
@@ -39,153 +38,60 @@ export function createPlatformInfo() {
39
38
  version: '',
40
39
  };
41
40
  }
42
- // The fixed point of the suite: a host backend that identifies the running platform. Resolves to the
43
- // registered native backend, or a lazily-created web backend so there is always an answer.
44
- export function createWebPlatformBackend() {
45
- return { getInfo: getWebPlatformInfo };
46
- }
47
- export function explainPlatformBackend() {
48
- if (_custom !== null) {
49
- return { conflict: _hostConflict, layer: 'custom', operation: null, viability: 'unobserved' };
50
- }
51
- if (_host !== null) {
52
- return {
53
- conflict: _hostConflict,
54
- layer: 'host',
55
- operation: _hostObservation !== null ? _hostObservation.operation : null,
56
- viability: _hostObservation !== null ? _hostObservation.viability : 'unobserved',
57
- };
58
- }
59
- return { conflict: false, layer: 'host-not-enabled', operation: null, viability: 'unobserved' };
60
- }
61
- // The active platform backend. Capability packages call their own get*Backend; this is the root
62
- // one for environment identification.
63
- export function getPlatformBackend() {
64
- return _custom ?? _host ?? _sentinel;
65
- }
66
41
  // The browser rendering engine — 'blink' | 'gecko' | 'webkit' | 'unknown'. Convenience over
67
42
  // getPlatformInfo. 'unknown' on native hosts where no browser engine is present.
68
- export function getPlatformEngine() {
69
- return getPlatformInfo(_scratch).engine;
43
+ export function getPlatformEngine(host) {
44
+ return getPlatformInfo(host, _scratch).engine;
70
45
  }
71
46
  // Fills `out` with the running platform's identity and returns it. Cheap; reads the active backend.
72
- export function getPlatformInfo(out) {
73
- return getPlatformBackend().getInfo(out);
47
+ export function getPlatformInfo(host, out) {
48
+ return host.system.platform.getInfo(out);
74
49
  }
75
50
  // The platform family — 'desktop' | 'mobile' | 'web' | 'unknown'. Convenience over getPlatformInfo.
76
- export function getPlatformKind() {
77
- return getPlatformInfo(_scratch).kind;
51
+ export function getPlatformKind(host) {
52
+ return getPlatformInfo(host, _scratch).kind;
78
53
  }
79
54
  // The specific OS/runtime name — 'windows' | 'macos' | 'ios' | 'android' | 'linux' | 'web' | 'unknown'.
80
- export function getPlatformName() {
81
- return getPlatformInfo(_scratch).name;
55
+ export function getPlatformName(host) {
56
+ return getPlatformInfo(host, _scratch).name;
82
57
  }
83
58
  // The host shell / runtime environment — 'web' | 'electron' | 'tauri' | 'capacitor' | 'native' |
84
59
  // 'unknown'. Convenience over getPlatformInfo. Distinguishes plain web from a host shell.
85
- export function getPlatformRuntime() {
86
- return getPlatformInfo(_scratch).runtime;
87
- }
88
- export function installPlatformHostBackend(backend) {
89
- if (_host !== null) {
90
- if (_host !== backend)
91
- _hostConflict = true;
92
- return;
93
- }
94
- _host = backend;
60
+ export function getPlatformRuntime(host) {
61
+ return getPlatformInfo(host, _scratch).runtime;
95
62
  }
96
63
  // True on a desktop host (Electron/Tauri/native window shell). False on mobile and plain web.
97
- export function isPlatformDesktop() {
98
- return getPlatformKind() === 'desktop';
64
+ export function isPlatformDesktop(host) {
65
+ return getPlatformKind(host) === 'desktop';
99
66
  }
100
67
  // True on a mobile host (iOS/Android via Capacitor or a native shell).
101
- export function isPlatformMobile() {
102
- return getPlatformKind() === 'mobile';
68
+ export function isPlatformMobile(host) {
69
+ return getPlatformKind(host) === 'mobile';
103
70
  }
104
71
  // True when the app is running inside a host shell (Electron/Tauri/Capacitor/native), not a plain
105
72
  // browser page. Convenience over `getPlatformRuntime() !== 'web' && !== 'unknown'`.
106
- export function isPlatformNative() {
107
- const runtime = getPlatformRuntime();
73
+ export function isPlatformNative(host) {
74
+ const runtime = getPlatformRuntime(host);
108
75
  return runtime !== 'web' && runtime !== 'unknown';
109
76
  }
110
77
  // True on a touch-primary device, independent of desktop/mobile classification.
111
- export function isPlatformTouch() {
112
- return getPlatformInfo(_scratch).isTouch;
78
+ export function isPlatformTouch(host) {
79
+ return getPlatformInfo(host, _scratch).isTouch;
113
80
  }
114
81
  // True when the running platform's OS version is at or above `minimum`. Reads the live version via
115
82
  // getPlatformInfo. Returns false when the version is '' (unknown). The comparison is numeric and
116
83
  // segment-wise (see comparePlatformVersions).
117
- export function isPlatformVersionAtLeast(minimum) {
118
- const version = getPlatformInfo(_scratch).version;
84
+ export function isPlatformVersionAtLeast(host, minimum) {
85
+ const version = getPlatformInfo(host, _scratch).version;
119
86
  if (version === '')
120
87
  return false;
121
88
  return comparePlatformVersions(version, minimum) >= 0;
122
89
  }
123
90
  // True when running as a plain web page with no native host registered.
124
- export function isPlatformWeb() {
125
- return getPlatformKind() === 'web';
126
- }
127
- export function observePlatformHostResult(operation, succeeded) {
128
- _hostObservation = {
129
- operation,
130
- viability: succeeded ? 'available' : 'runtime-api-unavailable',
131
- };
91
+ export function isPlatformWeb(host) {
92
+ return getPlatformKind(host) === 'web';
132
93
  }
133
- export function resetPlatformBackendForTest() {
134
- _custom = null;
135
- _host = null;
136
- _hostConflict = false;
137
- _hostObservation = null;
138
- }
139
- // Installs a native host backend (Electron/Tauri/Capacitor/native). Pass null to fall back to
140
- // the host or sentinel layer.
141
- export function setPlatformBackend(backend) {
142
- _custom = backend;
143
- }
144
- let _custom = null;
145
- let _host = null;
146
- let _hostConflict = false;
147
- let _hostObservation = null;
148
94
  // Single-threaded JS no-alloc scratch for scalar convenience reads (getPlatformKind, etc.).
149
95
  // Rust/native mirror uses a per-call local or thread-local instead.
150
96
  const _scratch = createPlatformInfo();
151
- const _sentinel = {
152
- getInfo(out) {
153
- out.arch = '';
154
- out.distro = '';
155
- out.distroVersion = '';
156
- out.endianness = 'unknown';
157
- out.engine = 'unknown';
158
- out.engineVersion = '';
159
- out.isTouch = false;
160
- out.kind = 'unknown';
161
- out.locale = '';
162
- out.name = 'unknown';
163
- out.osBuild = '';
164
- out.pointerWidth = -1;
165
- out.runtime = 'unknown';
166
- out.version = '';
167
- return out;
168
- },
169
- };
170
- function getWebPlatformInfo(out) {
171
- const nav = typeof navigator !== 'undefined' ? navigator : null;
172
- const ua = nav?.userAgent ?? '';
173
- out.name = parseUserAgentName(ua);
174
- out.kind = parseUserAgentKind(out.name);
175
- out.version = parseUserAgentVersion(ua, out.name);
176
- out.arch = parseUserAgentArch(ua);
177
- out.locale = nav?.language ?? '';
178
- out.isTouch =
179
- typeof navigator !== 'undefined' && 'maxTouchPoints' in navigator ? navigator.maxTouchPoints > 0 : false;
180
- out.runtime = parseUserAgentRuntime(typeof window !== 'undefined' ? window : null);
181
- out.engine = parseUserAgentEngine(ua);
182
- out.engineVersion = parseUserAgentEngineVersion(ua, out.engine);
183
- out.endianness = detectEndianness();
184
- out.pointerWidth = parseUserAgentPointerWidth(out.arch);
185
- // osBuild, distro, distroVersion are native-only; web always returns ''.
186
- out.osBuild = '';
187
- out.distro = '';
188
- out.distroVersion = '';
189
- return out;
190
- }
191
97
  //# sourceMappingURL=platform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/platform",
3
- "version": "0.5.0-next.1944.cd6b6e7",
3
+ "version": "0.5.1-edge.638.d4dbd4e",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,8 +38,8 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/types": "0.5.0-next.1944.cd6b6e7",
42
- "@flighthq/useragent": "0.5.0-next.1944.cd6b6e7"
41
+ "@flighthq/types": "0.5.1-edge.638.d4dbd4e",
42
+ "@flighthq/useragent": "0.5.1-edge.638.d4dbd4e"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.3.0"
@@ -1,10 +1,9 @@
1
- import type { PlatformBackend, PlatformInfo } from '@flighthq/types/contract';
1
+ import type { HasSystemPlatform, PlatformBackend, PlatformInfo } from '@flighthq/types/contract';
2
2
 
3
+ import * as platformContract from './platform';
3
4
  import {
4
5
  comparePlatformVersions,
5
6
  createPlatformInfo,
6
- createWebPlatformBackend,
7
- getPlatformBackend,
8
7
  getPlatformEngine,
9
8
  getPlatformInfo,
10
9
  getPlatformKind,
@@ -16,11 +15,6 @@ import {
16
15
  isPlatformTouch,
17
16
  isPlatformVersionAtLeast,
18
17
  isPlatformWeb,
19
- setPlatformBackend,
20
- explainPlatformBackend,
21
- installPlatformHostBackend,
22
- observePlatformHostResult,
23
- resetPlatformBackendForTest,
24
18
  } from './platform';
25
19
 
26
20
  function fakeBackend(info: Partial<PlatformInfo>): PlatformBackend {
@@ -32,7 +26,9 @@ function fakeBackend(info: Partial<PlatformInfo>): PlatformBackend {
32
26
  };
33
27
  }
34
28
 
35
- afterEach(() => setPlatformBackend(null));
29
+ function fakeHost(info: Partial<PlatformInfo>): HasSystemPlatform {
30
+ return { system: { platform: fakeBackend(info) } };
31
+ }
36
32
 
37
33
  describe('comparePlatformVersions', () => {
38
34
  it('returns 0 for identical strings', () => {
@@ -92,571 +88,157 @@ describe('createPlatformInfo', () => {
92
88
  });
93
89
  });
94
90
 
95
- describe('createWebPlatformBackend', () => {
96
- it('produces a backend that fills the out info', () => {
97
- const out = createPlatformInfo();
98
- const result = createWebPlatformBackend().getInfo(out);
99
- expect(result).toBe(out);
100
- expect(typeof result.name).toBe('string');
101
- });
102
-
103
- it('sets engine to a known canonical value', () => {
104
- const out = createPlatformInfo();
105
- createWebPlatformBackend().getInfo(out);
106
- expect(['blink', 'gecko', 'webkit', 'unknown']).toContain(out.engine);
107
- });
108
-
109
- it('sets runtime to a known canonical value', () => {
110
- const out = createPlatformInfo();
111
- createWebPlatformBackend().getInfo(out);
112
- expect(['web', 'electron', 'tauri', 'capacitor', 'native', 'unknown']).toContain(out.runtime);
113
- });
114
-
115
- it('sets kind to a known canonical value', () => {
116
- const out = createPlatformInfo();
117
- createWebPlatformBackend().getInfo(out);
118
- expect(['desktop', 'mobile', 'web', 'unknown']).toContain(out.kind);
119
- });
120
-
121
- it('sets name to a known canonical value', () => {
122
- const out = createPlatformInfo();
123
- createWebPlatformBackend().getInfo(out);
124
- expect(['web', 'windows', 'macos', 'linux', 'ios', 'android', 'unknown']).toContain(out.name);
125
- });
126
-
127
- it('sets endianness to a known canonical value', () => {
128
- const out = createPlatformInfo();
129
- createWebPlatformBackend().getInfo(out);
130
- expect(['little', 'big', 'unknown']).toContain(out.endianness);
131
- });
132
-
133
- it('sets pointerWidth to a known canonical value', () => {
134
- const out = createPlatformInfo();
135
- createWebPlatformBackend().getInfo(out);
136
- expect([-1, 32, 64]).toContain(out.pointerWidth);
137
- });
138
-
139
- it('sets osBuild, distro, distroVersion to empty string on web', () => {
140
- const out = createPlatformInfo();
141
- createWebPlatformBackend().getInfo(out);
142
- expect(out.osBuild).toBe('');
143
- expect(out.distro).toBe('');
144
- expect(out.distroVersion).toBe('');
145
- });
146
- });
147
-
148
- describe('explainPlatformBackend', () => {
149
- afterEach(() => resetPlatformBackendForTest());
150
-
151
- it('reports host-not-enabled when no backend is installed', () => {
152
- resetPlatformBackendForTest();
153
- const explanation = explainPlatformBackend();
154
- expect(explanation.layer).toBe('host-not-enabled');
155
- expect(explanation.conflict).toBe(false);
156
- expect(explanation.viability).toBe('unobserved');
157
- });
158
-
159
- it('reports custom layer when a custom backend is set', () => {
160
- setPlatformBackend(fakeBackend({}));
161
- expect(explainPlatformBackend().layer).toBe('custom');
162
- });
163
-
164
- it('reports host layer when a host backend is installed', () => {
165
- installPlatformHostBackend(fakeBackend({}));
166
- expect(explainPlatformBackend().layer).toBe('host');
167
- });
168
-
169
- it('reports conflict when two different host backends are installed', () => {
170
- installPlatformHostBackend(fakeBackend({}));
171
- installPlatformHostBackend(fakeBackend({}));
172
- expect(explainPlatformBackend().conflict).toBe(true);
173
- });
174
- });
175
-
176
- describe('getPlatformBackend', () => {
177
- it('falls back to a web backend when none is registered', () => {
178
- expect(getPlatformBackend()).not.toBeNull();
179
- });
180
-
181
- it('returns the registered backend', () => {
182
- const backend = fakeBackend({ kind: 'desktop', name: 'windows' });
183
- setPlatformBackend(backend);
184
- expect(getPlatformBackend()).toBe(backend);
185
- });
186
- });
187
-
188
91
  describe('getPlatformEngine', () => {
189
- it('returns the engine from the active backend', () => {
190
- setPlatformBackend(fakeBackend({ engine: 'blink' }));
191
- expect(getPlatformEngine()).toBe('blink');
92
+ it('returns the engine from the host backend', () => {
93
+ expect(getPlatformEngine(fakeHost({ engine: 'blink' }))).toBe('blink');
192
94
  });
193
95
 
194
96
  it('returns gecko when set', () => {
195
- setPlatformBackend(fakeBackend({ engine: 'gecko' }));
196
- expect(getPlatformEngine()).toBe('gecko');
97
+ expect(getPlatformEngine(fakeHost({ engine: 'gecko' }))).toBe('gecko');
197
98
  });
198
99
 
199
100
  it('returns webkit when set', () => {
200
- setPlatformBackend(fakeBackend({ engine: 'webkit' }));
201
- expect(getPlatformEngine()).toBe('webkit');
101
+ expect(getPlatformEngine(fakeHost({ engine: 'webkit' }))).toBe('webkit');
202
102
  });
203
103
 
204
104
  it('returns unknown for native backends', () => {
205
- setPlatformBackend(fakeBackend({ engine: 'unknown' }));
206
- expect(getPlatformEngine()).toBe('unknown');
105
+ expect(getPlatformEngine(fakeHost({ engine: 'unknown' }))).toBe('unknown');
207
106
  });
208
107
  });
209
108
 
210
109
  describe('getPlatformInfo', () => {
211
110
  it('fills and returns the out parameter', () => {
212
- setPlatformBackend(fakeBackend({ arch: 'arm64', kind: 'mobile', name: 'ios' }));
111
+ const host = fakeHost({ arch: 'arm64', kind: 'mobile', name: 'ios' });
213
112
  const out = createPlatformInfo();
214
- expect(getPlatformInfo(out)).toBe(out);
113
+ expect(getPlatformInfo(host, out)).toBe(out);
215
114
  expect(out.name).toBe('ios');
216
115
  expect(out.arch).toBe('arm64');
217
116
  });
218
117
  });
219
118
 
220
119
  describe('getPlatformKind', () => {
221
- it('returns the active backend kind', () => {
222
- setPlatformBackend(fakeBackend({ kind: 'desktop' }));
223
- expect(getPlatformKind()).toBe('desktop');
120
+ it('returns the host backend kind', () => {
121
+ expect(getPlatformKind(fakeHost({ kind: 'desktop' }))).toBe('desktop');
224
122
  });
225
123
  });
226
124
 
227
125
  describe('getPlatformName', () => {
228
- it('returns the active backend name', () => {
229
- setPlatformBackend(fakeBackend({ name: 'macos' }));
230
- expect(getPlatformName()).toBe('macos');
126
+ it('returns the host backend name', () => {
127
+ expect(getPlatformName(fakeHost({ name: 'macos' }))).toBe('macos');
231
128
  });
232
129
  });
233
130
 
234
131
  describe('getPlatformRuntime', () => {
235
132
  it('returns web when no host shell is detected', () => {
236
- setPlatformBackend(fakeBackend({ runtime: 'web' }));
237
- expect(getPlatformRuntime()).toBe('web');
133
+ expect(getPlatformRuntime(fakeHost({ runtime: 'web' }))).toBe('web');
238
134
  });
239
135
 
240
136
  it('returns electron when set', () => {
241
- setPlatformBackend(fakeBackend({ runtime: 'electron' }));
242
- expect(getPlatformRuntime()).toBe('electron');
137
+ expect(getPlatformRuntime(fakeHost({ runtime: 'electron' }))).toBe('electron');
243
138
  });
244
139
 
245
140
  it('returns tauri when set', () => {
246
- setPlatformBackend(fakeBackend({ runtime: 'tauri' }));
247
- expect(getPlatformRuntime()).toBe('tauri');
141
+ expect(getPlatformRuntime(fakeHost({ runtime: 'tauri' }))).toBe('tauri');
248
142
  });
249
143
 
250
144
  it('returns capacitor when set', () => {
251
- setPlatformBackend(fakeBackend({ runtime: 'capacitor' }));
252
- expect(getPlatformRuntime()).toBe('capacitor');
145
+ expect(getPlatformRuntime(fakeHost({ runtime: 'capacitor' }))).toBe('capacitor');
253
146
  });
254
147
 
255
148
  it('returns native when set by a native backend', () => {
256
- setPlatformBackend(fakeBackend({ runtime: 'native' }));
257
- expect(getPlatformRuntime()).toBe('native');
258
- });
259
- });
260
-
261
- describe('installPlatformHostBackend', () => {
262
- afterEach(() => resetPlatformBackendForTest());
263
-
264
- it('installs a host backend that getPlatformBackend returns', () => {
265
- const backend = fakeBackend({});
266
- installPlatformHostBackend(backend);
267
- expect(getPlatformBackend()).toBe(backend);
268
- });
269
-
270
- it('is first-host-wins: a second different backend sets conflict', () => {
271
- const first = fakeBackend({});
272
- const second = fakeBackend({});
273
- installPlatformHostBackend(first);
274
- installPlatformHostBackend(second);
275
- expect(getPlatformBackend()).toBe(first);
276
- expect(explainPlatformBackend().conflict).toBe(true);
149
+ expect(getPlatformRuntime(fakeHost({ runtime: 'native' }))).toBe('native');
277
150
  });
278
151
  });
279
152
 
280
153
  describe('isPlatformDesktop', () => {
281
154
  it('is true only for desktop kind', () => {
282
- setPlatformBackend(fakeBackend({ kind: 'desktop' }));
283
- expect(isPlatformDesktop()).toBe(true);
284
- setPlatformBackend(fakeBackend({ kind: 'web' }));
285
- expect(isPlatformDesktop()).toBe(false);
155
+ expect(isPlatformDesktop(fakeHost({ kind: 'desktop' }))).toBe(true);
156
+ expect(isPlatformDesktop(fakeHost({ kind: 'web' }))).toBe(false);
286
157
  });
287
158
  });
288
159
 
289
160
  describe('isPlatformMobile', () => {
290
161
  it('is true only for mobile kind', () => {
291
- setPlatformBackend(fakeBackend({ kind: 'mobile' }));
292
- expect(isPlatformMobile()).toBe(true);
162
+ expect(isPlatformMobile(fakeHost({ kind: 'mobile' }))).toBe(true);
293
163
  });
294
164
  });
295
165
 
296
166
  describe('isPlatformNative', () => {
297
167
  it('is true for electron runtime', () => {
298
- setPlatformBackend(fakeBackend({ runtime: 'electron' }));
299
- expect(isPlatformNative()).toBe(true);
168
+ expect(isPlatformNative(fakeHost({ runtime: 'electron' }))).toBe(true);
300
169
  });
301
170
 
302
171
  it('is true for tauri runtime', () => {
303
- setPlatformBackend(fakeBackend({ runtime: 'tauri' }));
304
- expect(isPlatformNative()).toBe(true);
172
+ expect(isPlatformNative(fakeHost({ runtime: 'tauri' }))).toBe(true);
305
173
  });
306
174
 
307
175
  it('is true for capacitor runtime', () => {
308
- setPlatformBackend(fakeBackend({ runtime: 'capacitor' }));
309
- expect(isPlatformNative()).toBe(true);
176
+ expect(isPlatformNative(fakeHost({ runtime: 'capacitor' }))).toBe(true);
310
177
  });
311
178
 
312
179
  it('is true for native runtime', () => {
313
- setPlatformBackend(fakeBackend({ runtime: 'native' }));
314
- expect(isPlatformNative()).toBe(true);
180
+ expect(isPlatformNative(fakeHost({ runtime: 'native' }))).toBe(true);
315
181
  });
316
182
 
317
183
  it('is false for web runtime', () => {
318
- setPlatformBackend(fakeBackend({ runtime: 'web' }));
319
- expect(isPlatformNative()).toBe(false);
184
+ expect(isPlatformNative(fakeHost({ runtime: 'web' }))).toBe(false);
320
185
  });
321
186
 
322
187
  it('is false for unknown runtime', () => {
323
- setPlatformBackend(fakeBackend({ runtime: 'unknown' }));
324
- expect(isPlatformNative()).toBe(false);
188
+ expect(isPlatformNative(fakeHost({ runtime: 'unknown' }))).toBe(false);
325
189
  });
326
190
  });
327
191
 
328
192
  describe('isPlatformTouch', () => {
329
193
  it('reflects the backend isTouch flag', () => {
330
- setPlatformBackend(fakeBackend({ isTouch: true }));
331
- expect(isPlatformTouch()).toBe(true);
194
+ expect(isPlatformTouch(fakeHost({ isTouch: true }))).toBe(true);
332
195
  });
333
196
  });
334
197
 
335
198
  describe('isPlatformVersionAtLeast', () => {
336
199
  it('is true when version equals minimum', () => {
337
- setPlatformBackend(fakeBackend({ version: '14.0' }));
338
- expect(isPlatformVersionAtLeast('14.0')).toBe(true);
200
+ expect(isPlatformVersionAtLeast(fakeHost({ version: '14.0' }), '14.0')).toBe(true);
339
201
  });
340
202
 
341
203
  it('is true when version exceeds minimum', () => {
342
- setPlatformBackend(fakeBackend({ version: '15.0' }));
343
- expect(isPlatformVersionAtLeast('14.0')).toBe(true);
204
+ expect(isPlatformVersionAtLeast(fakeHost({ version: '15.0' }), '14.0')).toBe(true);
344
205
  });
345
206
 
346
207
  it('is false when version is below minimum', () => {
347
- setPlatformBackend(fakeBackend({ version: '13.0' }));
348
- expect(isPlatformVersionAtLeast('14.0')).toBe(false);
208
+ expect(isPlatformVersionAtLeast(fakeHost({ version: '13.0' }), '14.0')).toBe(false);
349
209
  });
350
210
 
351
211
  it('is false when version is empty (unknown)', () => {
352
- setPlatformBackend(fakeBackend({ version: '' }));
353
- expect(isPlatformVersionAtLeast('1.0')).toBe(false);
212
+ expect(isPlatformVersionAtLeast(fakeHost({ version: '' }), '1.0')).toBe(false);
354
213
  });
355
214
 
356
215
  it('handles patch-level comparison', () => {
357
- setPlatformBackend(fakeBackend({ version: '10.15.7' }));
358
- expect(isPlatformVersionAtLeast('10.15.6')).toBe(true);
359
- expect(isPlatformVersionAtLeast('10.15.7')).toBe(true);
360
- expect(isPlatformVersionAtLeast('10.15.8')).toBe(false);
216
+ expect(isPlatformVersionAtLeast(fakeHost({ version: '10.15.7' }), '10.15.6')).toBe(true);
217
+ expect(isPlatformVersionAtLeast(fakeHost({ version: '10.15.7' }), '10.15.7')).toBe(true);
218
+ expect(isPlatformVersionAtLeast(fakeHost({ version: '10.15.7' }), '10.15.8')).toBe(false);
361
219
  });
362
220
  });
363
221
 
364
222
  describe('isPlatformWeb', () => {
365
223
  it('is true only for web kind', () => {
366
- setPlatformBackend(fakeBackend({ kind: 'web' }));
367
- expect(isPlatformWeb()).toBe(true);
368
- });
369
- });
370
-
371
- describe('observePlatformHostResult', () => {
372
- afterEach(() => resetPlatformBackendForTest());
373
-
374
- it('records a successful observation', () => {
375
- installPlatformHostBackend(fakeBackend({}));
376
- observePlatformHostResult('getInfo', true);
377
- const explanation = explainPlatformBackend();
378
- expect(explanation.operation).toBe('getInfo');
379
- expect(explanation.viability).toBe('available');
380
- });
381
-
382
- it('records a failed observation', () => {
383
- installPlatformHostBackend(fakeBackend({}));
384
- observePlatformHostResult('getInfo', false);
385
- expect(explainPlatformBackend().viability).toBe('runtime-api-unavailable');
386
- });
387
- });
388
-
389
- describe('resetPlatformBackendForTest', () => {
390
- it('clears all backend slots', () => {
391
- setPlatformBackend(fakeBackend({}));
392
- installPlatformHostBackend(fakeBackend({}));
393
- observePlatformHostResult('getInfo', true);
394
- resetPlatformBackendForTest();
395
- expect(explainPlatformBackend().layer).toBe('host-not-enabled');
396
- expect(explainPlatformBackend().conflict).toBe(false);
397
- expect(explainPlatformBackend().viability).toBe('unobserved');
224
+ expect(isPlatformWeb(fakeHost({ kind: 'web' }))).toBe(true);
398
225
  });
399
226
  });
400
227
 
401
- describe('setPlatformBackend', () => {
402
- it('clears back to the web fallback when passed null', () => {
403
- setPlatformBackend(fakeBackend({ name: 'linux' }));
404
- setPlatformBackend(null);
405
- expect(getPlatformBackend()).not.toBeNull();
406
- });
407
- });
408
-
409
- // Web backend UA-detection tests — use the internal createWebPlatformBackend to exercise detection
410
- // heuristics under controlled UA strings. These run in jsdom which may have its own navigator.
411
- describe('web backend UA detection', () => {
412
- // Helper: temporarily replace navigator.userAgent for a block (jsdom only).
413
- function withUserAgent(ua: string, fn: () => void): void {
414
- const original = navigator.userAgent;
415
- Object.defineProperty(navigator, 'userAgent', { configurable: true, value: ua });
416
- try {
417
- fn();
418
- } finally {
419
- Object.defineProperty(navigator, 'userAgent', { configurable: true, value: original });
420
- }
421
- }
422
-
423
- describe('arch detection', () => {
424
- it('detects arm64 from aarch64', () => {
425
- withUserAgent('Mozilla/5.0 (Linux; aarch64) AppleWebKit/537.36', () => {
426
- const out = createPlatformInfo();
427
- createWebPlatformBackend().getInfo(out);
428
- expect(out.arch).toBe('arm64');
429
- });
430
- });
431
-
432
- it('detects arm64 from arm64 token', () => {
433
- withUserAgent('Mozilla/5.0 (iPhone; CPU arm64)', () => {
434
- const out = createPlatformInfo();
435
- createWebPlatformBackend().getInfo(out);
436
- expect(out.arch).toBe('arm64');
437
- });
438
- });
439
-
440
- it('detects x64 from Win64', () => {
441
- withUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', () => {
442
- const out = createPlatformInfo();
443
- createWebPlatformBackend().getInfo(out);
444
- expect(out.arch).toBe('x64');
445
- });
446
- });
447
-
448
- it('detects x64 from WOW64', () => {
449
- withUserAgent('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36', () => {
450
- const out = createPlatformInfo();
451
- createWebPlatformBackend().getInfo(out);
452
- expect(out.arch).toBe('x64');
453
- });
454
- });
455
-
456
- it('returns empty string when arch is undetectable', () => {
457
- withUserAgent('Mozilla/5.0 (X11; Linux) AppleWebKit/537.36', () => {
458
- const out = createPlatformInfo();
459
- createWebPlatformBackend().getInfo(out);
460
- expect(out.arch).toBe('');
461
- });
462
- });
463
- });
464
-
465
- describe('canonical token normalization', () => {
466
- const KNOWN_NAMES = ['web', 'windows', 'macos', 'linux', 'ios', 'android', 'unknown'];
467
- const KNOWN_KINDS = ['desktop', 'mobile', 'web', 'unknown'];
468
- const KNOWN_RUNTIMES = ['web', 'electron', 'tauri', 'capacitor', 'native', 'unknown'];
469
- const KNOWN_ENGINES = ['blink', 'gecko', 'webkit', 'unknown'];
470
- const KNOWN_ENDIANNESSES = ['little', 'big', 'unknown'];
471
- const KNOWN_POINTER_WIDTHS = [-1, 32, 64];
472
-
473
- const TEST_UAS = [
474
- // Windows Chrome
475
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
476
- // macOS Safari
477
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
478
- // Firefox
479
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0',
480
- // iOS Safari
481
- 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15',
482
- // Android Chrome
483
- 'Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
228
+ describe('R3 boundary', () => {
229
+ it('exports no ambient-state API (setPlatformBackend, getPlatformBackend, etc.)', () => {
230
+ const exports = Object.keys(platformContract);
231
+ const deletedSymbols = [
232
+ 'createWebPlatformBackend',
233
+ 'explainPlatformBackend',
234
+ 'getPlatformBackend',
235
+ 'installPlatformHostBackend',
236
+ 'observePlatformHostResult',
237
+ 'resetPlatformBackendForTest',
238
+ 'setPlatformBackend',
484
239
  ];
485
-
486
- for (const ua of TEST_UAS) {
487
- it(`only emits known canonical tokens for UA: ${ua.slice(0, 60)}…`, () => {
488
- withUserAgent(ua, () => {
489
- const out = createPlatformInfo();
490
- createWebPlatformBackend().getInfo(out);
491
- expect(KNOWN_NAMES).toContain(out.name);
492
- expect(KNOWN_KINDS).toContain(out.kind);
493
- expect(KNOWN_RUNTIMES).toContain(out.runtime);
494
- expect(KNOWN_ENGINES).toContain(out.engine);
495
- expect(KNOWN_ENDIANNESSES).toContain(out.endianness);
496
- expect(KNOWN_POINTER_WIDTHS).toContain(out.pointerWidth);
497
- expect(typeof out.version).toBe('string');
498
- expect(typeof out.engineVersion).toBe('string');
499
- expect(typeof out.arch).toBe('string');
500
- });
501
- });
240
+ for (const symbol of deletedSymbols) {
241
+ expect(exports).not.toContain(symbol);
502
242
  }
503
243
  });
504
-
505
- describe('endianness detection', () => {
506
- it('returns a known canonical value', () => {
507
- const out = createPlatformInfo();
508
- createWebPlatformBackend().getInfo(out);
509
- expect(['little', 'big', 'unknown']).toContain(out.endianness);
510
- });
511
-
512
- it('returns little on jsdom (x64 host)', () => {
513
- // jsdom runs on Node.js on x64 hardware — always little-endian.
514
- const out = createPlatformInfo();
515
- createWebPlatformBackend().getInfo(out);
516
- expect(out.endianness).toBe('little');
517
- });
518
- });
519
-
520
- describe('engine detection', () => {
521
- it('detects blink from Chrome UA', () => {
522
- withUserAgent(
523
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
524
- () => {
525
- const out = createPlatformInfo();
526
- createWebPlatformBackend().getInfo(out);
527
- expect(out.engine).toBe('blink');
528
- },
529
- );
530
- });
531
-
532
- it('detects gecko from Firefox UA', () => {
533
- withUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0', () => {
534
- const out = createPlatformInfo();
535
- createWebPlatformBackend().getInfo(out);
536
- expect(out.engine).toBe('gecko');
537
- });
538
- });
539
-
540
- it('detects webkit from Safari UA', () => {
541
- withUserAgent(
542
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
543
- () => {
544
- const out = createPlatformInfo();
545
- createWebPlatformBackend().getInfo(out);
546
- expect(out.engine).toBe('webkit');
547
- },
548
- );
549
- });
550
- });
551
-
552
- describe('engineVersion detection', () => {
553
- it('extracts Firefox version', () => {
554
- withUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0', () => {
555
- const out = createPlatformInfo();
556
- createWebPlatformBackend().getInfo(out);
557
- expect(out.engineVersion).toBe('120.0');
558
- });
559
- });
560
-
561
- it('extracts Chrome version', () => {
562
- withUserAgent(
563
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.109 Safari/537.36',
564
- () => {
565
- const out = createPlatformInfo();
566
- createWebPlatformBackend().getInfo(out);
567
- expect(out.engineVersion).toBe('120.0.6099.109');
568
- },
569
- );
570
- });
571
-
572
- it('extracts Edge version (Edg/ token)', () => {
573
- withUserAgent(
574
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.2210.133',
575
- () => {
576
- const out = createPlatformInfo();
577
- createWebPlatformBackend().getInfo(out);
578
- expect(out.engineVersion).toBe('120.0.2210.133');
579
- },
580
- );
581
- });
582
-
583
- it('extracts Safari version from Version/ token', () => {
584
- withUserAgent(
585
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
586
- () => {
587
- const out = createPlatformInfo();
588
- createWebPlatformBackend().getInfo(out);
589
- expect(out.engineVersion).toBe('16.0');
590
- },
591
- );
592
- });
593
- });
594
-
595
- describe('pointerWidth detection', () => {
596
- it('returns 64 for x64 arch', () => {
597
- withUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', () => {
598
- const out = createPlatformInfo();
599
- createWebPlatformBackend().getInfo(out);
600
- expect(out.pointerWidth).toBe(64);
601
- });
602
- });
603
-
604
- it('returns 64 for arm64 arch', () => {
605
- withUserAgent('Mozilla/5.0 (Linux; aarch64) AppleWebKit/537.36', () => {
606
- const out = createPlatformInfo();
607
- createWebPlatformBackend().getInfo(out);
608
- expect(out.pointerWidth).toBe(64);
609
- });
610
- });
611
-
612
- it('returns -1 when arch is undetectable', () => {
613
- withUserAgent('Mozilla/5.0 (X11; Linux) AppleWebKit/537.36', () => {
614
- const out = createPlatformInfo();
615
- createWebPlatformBackend().getInfo(out);
616
- expect(out.pointerWidth).toBe(-1);
617
- });
618
- });
619
- });
620
-
621
- describe('version detection', () => {
622
- it('parses Windows version from NT string', () => {
623
- withUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64)', () => {
624
- const out = createPlatformInfo();
625
- createWebPlatformBackend().getInfo(out);
626
- expect(out.version).toBe('10.0');
627
- });
628
- });
629
-
630
- it('parses macOS version with underscore separators', () => {
631
- withUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)', () => {
632
- const out = createPlatformInfo();
633
- createWebPlatformBackend().getInfo(out);
634
- expect(out.version).toBe('10.15.7');
635
- });
636
- });
637
-
638
- it('parses iOS version', () => {
639
- withUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X)', () => {
640
- const out = createPlatformInfo();
641
- createWebPlatformBackend().getInfo(out);
642
- expect(out.version).toBe('17.4.1');
643
- });
644
- });
645
-
646
- it('parses Android version', () => {
647
- withUserAgent('Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36', () => {
648
- const out = createPlatformInfo();
649
- createWebPlatformBackend().getInfo(out);
650
- expect(out.version).toBe('14');
651
- });
652
- });
653
-
654
- it('returns empty string when version is undetectable', () => {
655
- withUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36', () => {
656
- const out = createPlatformInfo();
657
- createWebPlatformBackend().getInfo(out);
658
- expect(out.version).toBe('');
659
- });
660
- });
661
- });
662
244
  });