|
7 | 7 | assert(SHARED_MEMORY); |
8 | 8 |
|
9 | 9 | addToLibrary({ |
10 | | -// Chrome 87 shipped Atomics.waitAsync: |
11 | | -// https://www.chromestatus.com/feature/6243382101803008 |
12 | | -// However its implementation is faulty: |
13 | | -// https://bugs.chromium.org/p/chromium/issues/detail?id=1167541 |
14 | | -// Firefox Nightly 86.0a1 (2021-01-15) does not yet have it: |
15 | | -// https://bugzilla.mozilla.org/show_bug.cgi?id=1467846 |
16 | | -// And at the time of writing, no other browser has it either. |
17 | | -#if MIN_CHROME_VERSION < 91 || MIN_SAFARI_VERSION != TARGET_NOT_SUPPORTED || MIN_FIREFOX_VERSION != TARGET_NOT_SUPPORTED || ENVIRONMENT_MAY_BE_NODE |
18 | | - // Partially polyfill Atomics.waitAsync() if not available in the browser. |
19 | | - // Also polyfill for old Chrome-based browsers, where Atomics.waitAsync is |
20 | | - // broken until Chrome 91, see: |
21 | | - // https://bugs.chromium.org/p/chromium/issues/detail?id=1167541 |
22 | | - // https://github.com/tc39/proposal-atomics-wait-async/blob/master/PROPOSAL.md |
23 | | - // This polyfill performs polling with setTimeout() to observe a change in the |
24 | | - // target memory location. |
25 | | - $polyfillWaitAsync__postset: `if (!Atomics.waitAsync || (globalThis.navigator?.userAgent && Number((navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./)||[])[2]) < 91)) { |
26 | | - let __Atomics_waitAsyncAddresses = [/*[i32a, index, value, maxWaitMilliseconds, promiseResolve]*/]; |
27 | | - function __Atomics_pollWaitAsyncAddresses() { |
28 | | - let now = performance.now(); |
29 | | - let l = __Atomics_waitAsyncAddresses.length; |
30 | | - for (let i = 0; i < l; ++i) { |
31 | | - let a = __Atomics_waitAsyncAddresses[i]; |
32 | | - let expired = (now > a[3]); |
33 | | - let awoken = (Atomics.load(a[0], a[1]) != a[2]); |
34 | | - if (expired || awoken) { |
35 | | - __Atomics_waitAsyncAddresses[i--] = __Atomics_waitAsyncAddresses[--l]; |
36 | | - __Atomics_waitAsyncAddresses.length = l; |
37 | | - a[4](awoken ? 'ok': 'timed-out'); |
38 | | - } |
39 | | - } |
40 | | - if (l) { |
41 | | - // If we still have addresses to wait, loop the timeout handler to continue polling. |
42 | | - setTimeout(__Atomics_pollWaitAsyncAddresses, 10); |
43 | | - } |
44 | | - } |
45 | | - #if ASSERTIONS && WASM_WORKERS |
46 | | - if (!ENVIRONMENT_IS_WASM_WORKER) err('Current environment does not support Atomics.waitAsync(): polyfilling it, but this is going to be suboptimal.'); |
47 | | - #endif |
48 | | - /** |
49 | | - * @param {number=} maxWaitMilliseconds |
50 | | - */ |
51 | | - Atomics.waitAsync = (i32a, index, value, maxWaitMilliseconds) => { |
52 | | - let val = Atomics.load(i32a, index); |
53 | | - if (val != value) return { async: false, value: 'not-equal' }; |
54 | | - if (maxWaitMilliseconds <= 0) return { async: false, value: 'timed-out' }; |
55 | | - maxWaitMilliseconds = performance.now() + (maxWaitMilliseconds || Infinity); |
56 | | - let promiseResolve; |
57 | | - let promise = new Promise((resolve) => { promiseResolve = resolve; }); |
58 | | - if (!__Atomics_waitAsyncAddresses[0]) setTimeout(__Atomics_pollWaitAsyncAddresses, 10); |
59 | | - __Atomics_waitAsyncAddresses.push([i32a, index, value, maxWaitMilliseconds, promiseResolve]); |
60 | | - return { async: true, value: promise }; |
61 | | - }; |
62 | | -}`, |
63 | | -#endif |
64 | | - |
65 | | - $polyfillWaitAsync__internal: true, |
66 | | - $polyfillWaitAsync: () => { |
67 | | - // nop, used for its postset to ensure `Atomics.waitAsync()` polyfill is |
68 | | - // included exactly once and only included when needed. |
69 | | - // Any function using Atomics.waitAsync should depend on this. |
70 | | - }, |
71 | | - |
72 | 10 | $atomicWaitStates__internal: true, |
73 | 11 | $atomicWaitStates: ['ok', 'not-equal', 'timed-out'], |
74 | 12 | $liveAtomicWaitAsyncs: {}, |
75 | 13 | $liveAtomicWaitAsyncs__internal: true, |
76 | 14 | $liveAtomicWaitAsyncCounter: 0, |
77 | 15 | $liveAtomicWaitAsyncCounter__internal: true, |
78 | 16 |
|
79 | | - emscripten_atomic_wait_async__deps: ['$atomicWaitStates', '$liveAtomicWaitAsyncs', '$liveAtomicWaitAsyncCounter', '$polyfillWaitAsync', '$callUserCallback'], |
| 17 | + emscripten_atomic_wait_async__deps: ['$atomicWaitStates', '$liveAtomicWaitAsyncs', '$liveAtomicWaitAsyncCounter', '$callUserCallback'], |
80 | 18 | emscripten_atomic_wait_async: (addr, val, asyncWaitFinished, userData, maxWaitMilliseconds) => { |
81 | 19 | let wait = Atomics.waitAsync(HEAP32, {{{ getHeapOffset('addr', 'i32') }}}, val, maxWaitMilliseconds); |
82 | 20 | if (!wait.async) return atomicWaitStates.indexOf(wait.value); |
|
0 commit comments