From bad69c17887220e5530a19fc3afc97b454793be0 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 3 Dec 2025 14:56:11 -0800 Subject: [PATCH] Use async/await in libwebaudio.js. NFC --- src/lib/libwebaudio.js | 90 +++++++------ test/codesize/audio_worklet_wasm.expected.js | 119 +++++++++--------- ...nimal_runtime_code_size_audio_worklet.json | 4 +- 3 files changed, 112 insertions(+), 101 deletions(-) diff --git a/src/lib/libwebaudio.js b/src/lib/libwebaudio.js index af78d29ff6940..4d4c926dfbb33 100644 --- a/src/lib/libwebaudio.js +++ b/src/lib/libwebaudio.js @@ -119,17 +119,22 @@ var LibraryWebAudio = { #endif }, - emscripten_resume_audio_context_async: (contextHandle, callback, userData) => { + emscripten_resume_audio_context_async: async (contextHandle, callback, userData) => { function cb(state) { #if WEBAUDIO_DEBUG - console.log(`emscripten_resume_audio_context_async() callback: New audio state="${emAudio[contextHandle].state}", ID=${state}`); + dbg(`emscripten_resume_audio_context_async() callback: New audio state="${emAudio[contextHandle].state}", ID=${state}`); #endif {{{ makeDynCall('viip', 'callback') }}}(contextHandle, state, userData); } #if WEBAUDIO_DEBUG dbg('emscripten_resume_audio_context_async() resuming...'); #endif - emAudio[contextHandle].resume().then(() => { cb(1/*running*/) }).catch(() => { cb(0/*suspended*/) }); + try { + await emAudio[contextHandle].resume(); + cb(/*running*/); + } catch { + cb(0/*suspended*/); + } }, emscripten_resume_audio_context_sync: (contextHandle) => { @@ -171,8 +176,7 @@ var LibraryWebAudio = { '$_wasmWorkersID', '$_emAudioDispatchProcessorCallback', '$stackAlloc', '$stackRestore', '$stackSave'], - emscripten_start_wasm_audio_worklet_thread_async: (contextHandle, stackLowestAddress, stackSize, callback, userData) => { - + emscripten_start_wasm_audio_worklet_thread_async: async (contextHandle, stackLowestAddress, stackSize, callback, userData) => { #if ASSERTIONS || WEBAUDIO_DEBUG emAudioExpectContext(contextHandle, 'emscripten_start_wasm_audio_worklet_thread_async'); #endif @@ -212,55 +216,59 @@ var LibraryWebAudio = { return audioWorkletCreationFailed(); } - audioWorklet.addModule({{{ wasmWorkerJs }}}).then(() => { + try { + await audioWorklet.addModule({{{ wasmWorkerJs }}}); + } catch { + return audioWorkletCreationFailed(); + } + #if WEBAUDIO_DEBUG - dbg(`emscripten_start_wasm_audio_worklet_thread_async() addModule() completed`); + dbg(`emscripten_start_wasm_audio_worklet_thread_async() addModule() completed`); #endif #if MIN_FIREFOX_VERSION < 138 || MIN_CHROME_VERSION != TARGET_NOT_SUPPORTED || MIN_SAFARI_VERSION != TARGET_NOT_SUPPORTED - // If this browser does not support the up-to-date AudioWorklet standard - // that has a MessagePort over to the AudioWorklet, then polyfill that by - // instantiating a dummy AudioWorkletNode to get a MessagePort over. - // Firefox added support in https://hg-edge.mozilla.org/integration/autoland/rev/ab38a1796126f2b3fc06475ffc5a625059af59c1 - // Chrome ticket: https://crbug.com/446920095 - // Safari ticket: https://webkit.org/b/299386 - if (!audioWorklet['port']) { - audioWorklet['port'] = { - postMessage: (msg) => { - if (msg['_boot']) { - audioWorklet.bootstrapMessage = new AudioWorkletNode(audioContext, 'em-bootstrap', { - processorOptions: msg - }); - audioWorklet.bootstrapMessage['port'].onmessage = (msg) => { - audioWorklet['port'].onmessage(msg); - } - } else { - audioWorklet.bootstrapMessage['port'].postMessage(msg); + // If this browser does not support the up-to-date AudioWorklet standard + // that has a MessagePort over to the AudioWorklet, then polyfill that by + // instantiating a dummy AudioWorkletNode to get a MessagePort over. + // Firefox added support in https://hg-edge.mozilla.org/integration/autoland/rev/ab38a1796126f2b3fc06475ffc5a625059af59c1 + // Chrome ticket: https://crbug.com/446920095 + // Safari ticket: https://webkit.org/b/299386 + if (!audioWorklet['port']) { + audioWorklet['port'] = { + postMessage: (msg) => { + if (msg['_boot']) { + audioWorklet.bootstrapMessage = new AudioWorkletNode(audioContext, 'em-bootstrap', { + processorOptions: msg + }); + audioWorklet.bootstrapMessage['port'].onmessage = (msg) => { + audioWorklet['port'].onmessage(msg); } + } else { + audioWorklet.bootstrapMessage['port'].postMessage(msg); } } } + } #endif - audioWorklet['port'].postMessage({ - // This is the bootstrap message to the Audio Worklet. - '_boot': 1, - // Assign the loaded AudioWorkletGlobalScope a Wasm Worker ID so that - // it can utilized its own TLS slots, and it is recognized to not be - // the main browser thread. - wwID: _wasmWorkersID++, + audioWorklet['port'].postMessage({ + // This is the bootstrap message to the Audio Worklet. + '_boot': 1, + // Assign the loaded AudioWorkletGlobalScope a Wasm Worker ID so that + // it can utilized its own TLS slots, and it is recognized to not be + // the main browser thread. + wwID: _wasmWorkersID++, #if MINIMAL_RUNTIME - wasm: Module['wasm'], + wasm: Module['wasm'], #else - wasm: wasmModule, + wasm: wasmModule, #endif - wasmMemory, - stackLowestAddress, // sb = stack base - stackSize, // sz = stack size - }); - audioWorklet['port'].onmessage = _emAudioDispatchProcessorCallback; - {{{ makeDynCall('viip', 'callback') }}}(contextHandle, 1/*EM_TRUE*/, userData); - }).catch(audioWorkletCreationFailed); + wasmMemory, + stackLowestAddress, // sb = stack base + stackSize, // sz = stack size + }); + audioWorklet['port'].onmessage = _emAudioDispatchProcessorCallback; + {{{ makeDynCall('viip', 'callback') }}}(contextHandle, 1/*EM_TRUE*/, userData); }, $_emAudioDispatchProcessorCallback__deps: ['$getWasmTableEntry'], diff --git a/test/codesize/audio_worklet_wasm.expected.js b/test/codesize/audio_worklet_wasm.expected.js index f18e8adf6f120..a78320f2ad36d 100644 --- a/test/codesize/audio_worklet_wasm.expected.js +++ b/test/codesize/audio_worklet_wasm.expected.js @@ -1,8 +1,8 @@ -var m = globalThis.Module || "undefined" != typeof Module ? Module : {}, p = !!globalThis.AudioWorkletGlobalScope, t = "em-ww" == globalThis.name || p, u, z, I, J, G, E, w, X, F, D, C, Y, A, Z; +var m = globalThis.Module || "undefined" != typeof Module ? Module : {}, p = !!globalThis.AudioWorkletGlobalScope, q = "em-ww" == globalThis.name || p, t, z, I, J, G, E, v, X, F, D, C, Y, A, Z; -function v(a) { - u = a; - w = a.L; +function u(a) { + t = a; + v = a.L; x(); m ||= {}; m.wasm = a.G; @@ -10,14 +10,14 @@ function v(a) { a.G = a.M = 0; } -t && !p && (onmessage = a => { +q && !p && (onmessage = a => { onmessage = null; - v(a.data); + u(a.data); }); if (p) { function a(b) { - class h extends AudioWorkletProcessor { + class f extends AudioWorkletProcessor { constructor(d) { super(); d = d.processorOptions; @@ -25,7 +25,7 @@ if (p) { this.A = d.A; this.u = d.u; this.s = 4 * this.u; - this.B = Array(Math.min((u.F - 16) / this.s | 0, 64)); + this.B = Array(Math.min((t.F - 16) / this.s | 0, 64)); this.K(); } K() { @@ -36,43 +36,43 @@ if (p) { return b; } process(d, g, e) { - var l = d.length, q = g.length, f, r, k = 12 * (l + q), n = 0; - for (f of d) n += f.length; + var l = d.length, w = g.length, h, r, k = 12 * (l + w), n = 0; + for (h of d) n += h.length; n *= this.s; var H = 0; - for (f of g) H += f.length; + for (h of g) H += h.length; n += H * this.s; var N = 0; - for (f in e) ++N, k += 8, n += e[f].byteLength; + for (h in e) ++N, k += 8, n += e[h].byteLength; var U = C(), B = k + n + 15 & -16; k = D(B); n = k + (B - n); B = k; - for (f of d) { - G[k >> 2] = f.length; + for (h of d) { + G[k >> 2] = h.length; G[k + 4 >> 2] = this.u; G[k + 8 >> 2] = n; k += 12; - for (r of f) E.set(r, n >> 2), n += this.s; + for (r of h) E.set(r, n >> 2), n += this.s; } d = k; - for (f = 0; r = e[f++]; ) G[k >> 2] = r.length, G[k + 4 >> 2] = n, k += 8, E.set(r, n >> 2), + for (h = 0; r = e[h++]; ) G[k >> 2] = r.length, G[k + 4 >> 2] = n, k += 8, E.set(r, n >> 2), n += 4 * r.length; e = k; - for (f of g) G[k >> 2] = f.length, G[k + 4 >> 2] = this.u, G[k + 8 >> 2] = n, k += 12, - n += this.s * f.length; - if (l = this.v(l, B, q, e, N, d, this.A)) for (f of g) for (r of f) r.set(this.B[--H]); + for (h of g) G[k >> 2] = h.length, G[k + 4 >> 2] = this.u, G[k + 8 >> 2] = n, k += 12, + n += this.s * h.length; + if (l = this.v(l, B, w, e, N, d, this.A)) for (h of g) for (r of h) r.set(this.B[--H]); F(U); return !!l; } } - return h; + return f; } var port = globalThis.port || {}; class c extends AudioWorkletProcessor { constructor(b) { super(); - v(b.processorOptions); + u(b.processorOptions); port instanceof MessagePort || (this.port.onmessage = port.onmessage, port = this.port); } process() {} @@ -81,7 +81,7 @@ if (p) { port.onmessage = async b => { await z; b = b.data; - b._boot ? v(b) : b._wpn ? (registerProcessor(b._wpn, a(b.H)), port.postMessage({ + b._boot ? u(b) : b._wpn ? (registerProcessor(b._wpn, a(b.H)), port.postMessage({ _wsc: b.v, C: [ b.I, 1, b.A ] })) : b._wsc && A.get(b._wsc)(...b.C); @@ -89,14 +89,14 @@ if (p) { } function x() { - var a = w.buffer; + var a = v.buffer; I = new Uint8Array(a); J = new Int32Array(a); G = new Uint32Array(a); E = new Float32Array(a); } -t || (w = m.mem || new WebAssembly.Memory({ +q || (v = m.mem || new WebAssembly.Memory({ initial: 256, maximum: 256, shared: !0 @@ -108,24 +108,24 @@ var K = [], L = a => { c && A.get(c)(...a.x); }, M = a => { K.push(a); -}, P = (a, c, b, h) => { +}, P = (a, c, b, f) => { c = O[c]; - O[a].connect(c.destination || c, b, h); + O[a].connect(c.destination || c, b, f); }, O = {}, Q = 0, R = globalThis.TextDecoder && new TextDecoder, S = (a = 0) => { - for (var c = I, b = a, h = b + void 0; c[b] && !(b >= h); ) ++b; + for (var c = I, b = a, f = b + void 0; c[b] && !(b >= f); ) ++b; if (16 < b - a && c.buffer && R) return R.decode(c.slice(a, b)); - for (h = ""; a < b; ) { + for (f = ""; a < b; ) { var d = c[a++]; if (d & 128) { var g = c[a++] & 63; - if (192 == (d & 224)) h += String.fromCharCode((d & 31) << 6 | g); else { + if (192 == (d & 224)) f += String.fromCharCode((d & 31) << 6 | g); else { var e = c[a++] & 63; d = 224 == (d & 240) ? (d & 15) << 12 | g << 6 | e : (d & 7) << 18 | g << 12 | e << 6 | c[a++] & 63; - 65536 > d ? h += String.fromCharCode(d) : (d -= 65536, h += String.fromCharCode(55296 | d >> 10, 56320 | d & 1023)); + 65536 > d ? f += String.fromCharCode(d) : (d -= 65536, f += String.fromCharCode(55296 | d >> 10, 56320 | d & 1023)); } - } else h += String.fromCharCode(d); + } else f += String.fromCharCode(d); } - return h; + return f; }, T = a => { if (a) { var c = G[a >> 2]; @@ -140,14 +140,14 @@ var K = [], L = a => { a = new AudioContext(a); O[++Q] = a; return Q; -}, V = (a, c, b, h, d) => { +}, V = (a, c, b, f, d) => { var g = b ? J[b + 4 >> 2] : 0; if (b) { - var e = J[b >> 2], l = G[b + 8 >> 2], q = g; + var e = J[b >> 2], l = G[b + 8 >> 2], w = g; if (l) { l >>= 2; - for (var f = []; q--; ) f.push(G[l++]); - l = f; + for (var h = []; w--; ) h.push(G[l++]); + l = h; } else l = void 0; b = { numberOfInputs: e, @@ -157,7 +157,7 @@ var K = [], L = a => { channelCountMode: [ , "clamped-max", "explicit" ][J[b + 16 >> 2]], channelInterpretation: [ , "discrete" ][J[b + 20 >> 2]], processorOptions: { - v: h, + v: f, A: d, u: O[a].renderQuantumSize || 128 } @@ -166,7 +166,7 @@ var K = [], L = a => { a = new AudioWorkletNode(O[a], c ? S(c) : "", b); O[++Q] = a; return Q; -}, W = (a, c, b, h) => { +}, W = (a, c, b, f) => { var d = (d = G[c >> 2]) ? S(d) : "", g = J[c + 4 >> 2]; c = G[c + 8 >> 2]; for (var e = [], l = 0; g--; ) e.push({ @@ -181,38 +181,41 @@ var K = [], L = a => { H: e, I: a, v: b, - A: h + A: f }); }, aa = () => !1, ba = 1, ca = a => { a = a.data; var c = a._wsc; c && A.get(c)(...a.C); -}, da = (a, c, b, h, d) => { - var g = O[a], e = g.audioWorklet, l = () => { - A.get(h)(a, 0, d); - }; - if (!e) return l(); - e.addModule(m.js).then((() => { +}, da = async (a, c, b, f, d) => { + var g = O[a], e = g.audioWorklet; + if (e) { + try { + await e.addModule(m.js); + } catch { + A.get(f)(a, 0, d); + return; + } e.port || (e.port = { - postMessage: q => { - q._boot ? (e.D = new AudioWorkletNode(g, "em-bootstrap", { - processorOptions: q - }), e.D.port.onmessage = f => { - e.port.onmessage(f); - }) : e.D.port.postMessage(q); + postMessage: l => { + l._boot ? (e.D = new AudioWorkletNode(g, "em-bootstrap", { + processorOptions: l + }), e.D.port.onmessage = w => { + e.port.onmessage(w); + }) : e.D.port.postMessage(l); } }); e.port.postMessage({ _boot: 1, O: ba++, G: m.wasm, - L: w, + L: v, J: c, F: b }); e.port.onmessage = ca; - A.get(h)(a, 1, d); - })).catch(l); + A.get(f)(a, 1, d); + } else A.get(f)(a, 0, d); }; function ea(a) { @@ -234,7 +237,7 @@ function y() { e: W, b: aa, c: da, - a: w + a: v }; z = WebAssembly.instantiate(m.wasm, { a: Z @@ -246,9 +249,9 @@ function y() { C = a.n; Y = a.o; A = a.k; - t ? (Y(u.J, u.F), p || (removeEventListener("message", M), K = K.forEach(L), addEventListener("message", L))) : a.i(); - t || X(); + q ? (Y(t.J, t.F), p || (removeEventListener("message", M), K = K.forEach(L), addEventListener("message", L))) : a.i(); + q || X(); })); } -t || y(); \ No newline at end of file +q || y(); \ No newline at end of file diff --git a/test/codesize/test_minimal_runtime_code_size_audio_worklet.json b/test/codesize/test_minimal_runtime_code_size_audio_worklet.json index 50ff7beecdafb..9c053291715cb 100644 --- a/test/codesize/test_minimal_runtime_code_size_audio_worklet.json +++ b/test/codesize/test_minimal_runtime_code_size_audio_worklet.json @@ -1,10 +1,10 @@ { "a.html": 519, "a.html.gz": 357, - "a.js": 4309, + "a.js": 4318, "a.js.gz": 2219, "a.wasm": 1329, "a.wasm.gz": 895, - "total": 6157, + "total": 6166, "total_gz": 3471 }