diff --git a/cc.config.json b/cc.config.json index 8c605cfda11..797a1b92438 100644 --- a/cc.config.json +++ b/cc.config.json @@ -666,6 +666,12 @@ "type": "boolean", "value": false, "internal": true + }, + "WASM_FALLBACK": { + "comment": "An internal constant to indicate whether need a fallback of wasm.\nIf true, we build a wasm fallback module for the compatibility of wasm files compiled by different version of emscripten.\nThis is useful when we use wasm on different version of Safari browsers.", + "type": "boolean", + "value": "$HTML5", + "internal": true } }, diff --git a/cocos/spine/lib/instantiated.ts b/cocos/spine/lib/instantiated.ts index 7986515383a..4b3ae00f94b 100644 --- a/cocos/spine/lib/instantiated.ts +++ b/cocos/spine/lib/instantiated.ts @@ -23,7 +23,8 @@ */ import { instantiateWasm, fetchBuffer } from 'pal/wasm'; -import { JSB, WASM_SUPPORT_MODE, CULL_ASM_JS_MODULE } from 'internal:constants'; +import { systemInfo } from 'pal/system-info'; +import { JSB, WASM_SUPPORT_MODE, CULL_ASM_JS_MODULE, WASM_FALLBACK, HTML5 } from 'internal:constants'; import asmFactory from 'external:emscripten/spine/spine.asm.js'; import asmJsMemUrl from 'external:emscripten/spine/spine.js.mem'; import wasmFactory from 'external:emscripten/spine/spine.wasm.js'; @@ -32,6 +33,7 @@ import { game } from '../../game'; import { getError, error, sys } from '../../core'; import { WebAssemblySupportMode } from '../../misc/webassembly-support'; import { overrideSpineDefine } from './spine-define'; +import { BrowserType } from '../../../pal/system-info/enum-type'; const PAGESIZE = 65536; // 64KiB @@ -48,6 +50,36 @@ const registerList: any[] = []; function initWasm (wasmUrl): Promise { return new Promise((resolve, reject) => { const errorMessage = (err: any): string => `[Spine]: Spine wasm load failed: ${err}`; + if (WASM_FALLBACK) { + if (HTML5 && systemInfo.isMobile && systemInfo.browserType === BrowserType.SAFARI) { + const safariVersion = /Version\/([\d.]+)/.exec(window.navigator.userAgent)?.[1]; + if (safariVersion && Number.parseInt(safariVersion.split('.')[0]) < 15) { + // NOTE: we need to fallback to the wasm which is compiled by lower version of emscripten. + Promise.all([ + import('external:emscripten/spine/spine.wasm.fallback'), + import('external:emscripten/spine/spine.wasm.fallback.js')]).then(([ + { default: wasmFallbackUrl }, + { default: wasmFallbackFactory }, + ]) => { + wasmFallbackFactory({ + instantiateWasm (importObject: WebAssembly.Imports, + receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) { + // NOTE: the Promise return by instantiateWasm hook can't be caught. + instantiateWasm(wasmFallbackUrl, importObject).then((result: any) => { + receiveInstance(result.instance, result.module); + }).catch((err) => reject(errorMessage(err))); + }, + }).then((Instance: any) => { + wasmInstance = Instance; + registerList.forEach((cb) => { + cb(wasmInstance); + }); + }).then(resolve).catch((err: any) => reject(errorMessage(err))); + }).catch(reject); + return; + } + } + } wasmFactory({ instantiateWasm (importObject: WebAssembly.Imports, receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) { diff --git a/native/external-config.json b/native/external-config.json index e98ebde87c0..5248be1952e 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.0-8" + "checkout": "v3.8.0-9" } }