// import decompress from 'brotli/decompress' import Go from '../go_wams_exec' import { parseURL } from '.' async function instantiateStreaming(resp, importObject, brotliCompressed = false) { if (brotliCompressed || !WebAssembly.instantiateStreaming) { const source = await (await resp).arrayBuffer() if (brotliCompressed) { throw new Error('do not support *.br') } // const buffer = brotliCompressed ? decompress(new Int8Array(source)) : source const buffer = source return WebAssembly.instantiate(buffer, importObject) } return WebAssembly.instantiateStreaming(resp, importObject) } function isBrotliCompressed(url) { let brotliCompressed = false let pathname = '' try { const location = parseURL(url) pathname = location.pathname } catch (e) { pathname = url } if (/\.br$/.test(pathname)) { brotliCompressed = true } return brotliCompressed } export async function getExportFunction(url, module, mode = 'go') { let importObject = { env: { memoryBase: 0, tableBase: 0, memory: new WebAssembly.Memory({ initial: 256, }), // table: new WebAssembly.Table({ // initial: 2, // element: 'anyfunc', // }), }, ...module, } let go const brotliCompressed = isBrotliCompressed(url) if (mode === 'go') { go = new Go() go._initedModulePromise = new Promise((resolve) => { go._initedModuleResolve = resolve }) importObject = { ...go.importObject, env: { ...go.importObject.env, exportModule(module) { return go._initedModuleResolve(module) }, }, } } const reuslt = await instantiateStreaming(fetch(url), importObject, brotliCompressed) if (mode === 'go') { await Promise.race([ go.run(reuslt.instance), new Promise(resolve => setTimeout(() => { resolve(null) }, 500),), ]) return { callContainer: (window as any).callContainer, initContainer: (window as any).initContainer, } } // if (mode === 'go') { // go.run(reuslt.instance) // const module = await go._initedModulePromise // return module // } return reuslt.instance.exports } export async function loadJSExportFunction(config?: { vm: string; vender?: string }) { const { vm, vender } = config || {} const VENDER_KEY = 'cloudbase_private_link_vender' if (vender || !Object.prototype.hasOwnProperty.call(document.defaultView, VENDER_KEY)) { await loadUmdModule( vender || 'https://qbase.cdn-go.cn/lcap/lcap-resource-cdngo/-/release/_npm/@cloudbase/privatelink-vender@0.0.2/dist/cdn/cloudbase.privatelink.vender.js', VENDER_KEY, ) } return loadUmdModule( vm || 'https://qbase.cdn-go.cn/lcap/lcap-resource-cdngo/-/release/_npm/@cloudbase/privatelink@0.0.1/dist/cdn/cloudbase.privatelink.vm.js', 'cloudbase_private_link', ) } function loadUmdModule(jsUrl: string, umdModuleName: string, targetDoc: Document = document) { return new Promise((resolve, reject) => { const win = targetDoc.defaultView const script = targetDoc.createElement('script') script.setAttribute('src', jsUrl) script.setAttribute('class', umdModuleName) script.addEventListener('load', () => { if (Object.prototype.hasOwnProperty.call(win, umdModuleName)) { return resolve(win[umdModuleName as any]) } const error = new Error(`Fail to load UMD module ${umdModuleName} from [${jsUrl}].`) return reject(error) }) script.addEventListener('error', (e) => { const error = new Error(`main bundle [${umdModuleName}] load failed from [${jsUrl}]: ${e?.message || ''}`) reject(error) }) if (targetDoc.body) { targetDoc.body.appendChild(script) } else { targetDoc.head.appendChild(script) } }) }