Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions ui/ceval/src/engines/engines.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { BrowserEngineInfo, ExternalEngineInfo, EngineInfo, CevalEngine, Requires } from '../types';
import type { BrowserEngineInfo, ExternalEngineInfo, EngineInfo, CevalEngine } from '../types';
import type CevalCtrl from '../ctrl';
import { SimpleEngine } from './simpleEngine';
import { StockfishWebEngine } from './stockfishWebEngine';
import { ThreadedEngine } from './threadedEngine';
import { ExternalEngine } from './externalEngine';
import { storedStringProp, StoredProp } from 'common/storage';
import { isAndroid, isIOS, isIPad, getFirefoxMajorVersion, features, type Feature } from 'common/device';
import { isAndroid, isIOS, isIPad, features as browserSupport, type Feature } from 'common/device';
import { xhrHeader } from 'common/xhr';
import { lichessRules } from 'chessops/compat';
import { log } from 'common/permalog';
Expand All @@ -16,12 +16,8 @@ export class Engines {
localEngineMap: Map<string, WithMake>;
externalEngines: ExternalEngineInfo[];
selectProp: StoredProp<string>;
browserSupport: Requires[] = features().slice();

constructor(private ctrl: CevalCtrl) {
const firefox = getFirefoxMajorVersion();
if (!firefox || firefox > 113) this.browserSupport.push('allowLsfw');

this.localEngineMap = this.makeEngineMap();
this.localEngines = [...this.localEngineMap.values()].map(e => e.info);
this.externalEngines = this.ctrl.opts.externalEngines?.map(e => ({ tech: 'EXTERNAL', ...e })) ?? [];
Expand All @@ -47,7 +43,7 @@ export class Engines {
name: 'Fairy Stockfish 14+ NNUE',
short: 'FSF 14+',
tech: 'NNUE',
requires: ['simd', 'allowLsfw'],
requires: ['simd', 'dynamicImportFromWorker'],
variants: [key],
assets: {
version: 'sfw006',
Expand Down Expand Up @@ -75,7 +71,7 @@ export class Engines {
name: 'Stockfish 16 NNUE · 7MB',
short: 'SF 16 · 7MB',
tech: 'NNUE',
requires: ['simd', 'allowLsfw'],
requires: ['simd', 'dynamicImportFromWorker'],
minMem: 1536,
assets: {
version: 'sfw006',
Expand All @@ -91,7 +87,7 @@ export class Engines {
name: 'Stockfish 17 NNUE · 79MB',
short: 'SF 17 · 79MB',
tech: 'NNUE',
requires: ['simd', 'allowLsfw'],
requires: ['simd', 'dynamicImportFromWorker'],
minMem: 2560,
assets: {
version: 'sfw006',
Expand Down Expand Up @@ -126,7 +122,7 @@ export class Engines {
name: 'Fairy Stockfish 14+ HCE',
short: 'FSF 14+',
tech: 'HCE',
requires: ['simd', 'allowLsfw'],
requires: ['simd', 'dynamicImportFromWorker'],
variants: variants.map(v => v[0]),
assets: {
version: 'sfw006',
Expand Down Expand Up @@ -214,8 +210,8 @@ export class Engines {
]
.filter(
e =>
e.info.requires.every((req: Requires) => this.browserSupport.includes(req)) &&
!(e.info.obsoletedBy && this.browserSupport.includes(e.info.obsoletedBy as Feature)),
e.info.requires.every((req: Feature) => browserSupport().includes(req)) &&
!(e.info.obsoletedBy && browserSupport().includes(e.info.obsoletedBy as Feature)),
)
.map(e => [e.info.id, { info: withDefaults(e.info as BrowserEngineInfo), make: e.make }]),
);
Expand Down
6 changes: 2 additions & 4 deletions ui/ceval/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export interface BaseEngineInfo {
minThreads?: number;
maxThreads?: number;
maxHash?: number;
requires?: Requires[];
requires?: Feature[];
}

export interface ExternalEngineInfo extends BaseEngineInfo {
Expand All @@ -46,14 +46,12 @@ export interface ExternalEngineInfo extends BaseEngineInfo {
export interface BrowserEngineInfo extends BaseEngineInfo {
minMem?: number;
assets: { root?: string; js?: string; wasm?: string; version?: string; nnue?: string[] };
requires: Requires[];
requires: Feature[];
obsoletedBy?: Feature;
}

export type EngineInfo = BrowserEngineInfo | ExternalEngineInfo;

export type Requires = Feature | 'allowLsfw'; // lsfw = lila-stockfish-web

export type EngineNotifier = (status?: {
download?: { bytes: number; total: number };
error?: string;
Expand Down
12 changes: 11 additions & 1 deletion ui/common/src/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export const isApple: () => boolean = memoize<boolean>(

export const shareIcon: () => string = () => (isApple() ? licon.ShareIos : licon.ShareAndroid);

export type Feature = 'wasm' | 'sharedMem' | 'simd';
export type Feature = 'wasm' | 'sharedMem' | 'simd' | 'dynamicImportFromWorker';

export const hasFeature = (feat?: string): boolean => !feat || features().includes(feat as Feature);

Expand All @@ -121,6 +121,16 @@ export const features: () => readonly Feature[] = memoize<readonly Feature[]>(()
]);
if (WebAssembly.validate(sourceWithSimd)) features.push('simd');
}
try {
new Worker(
URL.createObjectURL(
new Blob(["import('data:text/javascript,export default {}')"], { type: 'application/javascript' }),
),
).terminate();
features.push('dynamicImportFromWorker');
} catch {
// no dynamic import from worker
}
}
return Object.freeze(features);
});
Expand Down
4 changes: 3 additions & 1 deletion ui/puzzle/src/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export default class Report {
// the `mate` key theme is not sent, as it is considered redubant with `mateInX`
ctrl.data.puzzle.themes.some((t: ThemeKey) => t.toLowerCase().includes('mate')) ||
// if the user has chosen to hide the dialog less than a week ago
this.tsHideReportDialog() > Date.now() - 1000 * 3600 * 24 * 7
this.tsHideReportDialog() > Date.now() - 1000 * 3600 * 24 * 7 ||
// dynamic import from web worker feature is shared by all stockfish 16+ WASMs
!ctrl.ceval.engines.active?.requires?.includes('dynamicImportFromWorker')
)
return;
const node = ctrl.node;
Expand Down