diff --git a/ui/ceval/src/engines/engines.ts b/ui/ceval/src/engines/engines.ts index c4d876724ebff..982382d5776a7 100644 --- a/ui/ceval/src/engines/engines.ts +++ b/ui/ceval/src/engines/engines.ts @@ -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'; @@ -16,12 +16,8 @@ export class Engines { localEngineMap: Map; externalEngines: ExternalEngineInfo[]; selectProp: StoredProp; - 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 })) ?? []; @@ -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', @@ -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', @@ -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', @@ -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', @@ -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 }]), ); diff --git a/ui/ceval/src/types.ts b/ui/ceval/src/types.ts index bfd85f1d34ca4..526a19ab2c9c4 100644 --- a/ui/ceval/src/types.ts +++ b/ui/ceval/src/types.ts @@ -34,7 +34,7 @@ export interface BaseEngineInfo { minThreads?: number; maxThreads?: number; maxHash?: number; - requires?: Requires[]; + requires?: Feature[]; } export interface ExternalEngineInfo extends BaseEngineInfo { @@ -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; diff --git a/ui/common/src/device.ts b/ui/common/src/device.ts index 3826875adff52..616ef24a2e8c2 100644 --- a/ui/common/src/device.ts +++ b/ui/common/src/device.ts @@ -99,7 +99,7 @@ export const isApple: () => boolean = memoize( 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); @@ -121,6 +121,16 @@ export const features: () => readonly Feature[] = memoize(() ]); 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); }); diff --git a/ui/puzzle/src/report.ts b/ui/puzzle/src/report.ts index 34947bcafaba6..6cb96ded6c143 100644 --- a/ui/puzzle/src/report.ts +++ b/ui/puzzle/src/report.ts @@ -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;