|
'use strict'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
const {CHANNEL} = require('./channel.js'); |
|
|
|
const {isArray} = Array; |
|
|
|
let {SharedArrayBuffer, window} = globalThis; |
|
let {notify, wait, waitAsync} = Atomics; |
|
let postPatched = null; |
|
|
|
|
|
if (!waitAsync) { |
|
waitAsync = buffer => ({ |
|
value: new Promise(onmessage => { |
|
|
|
let w = new Worker('data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))'); |
|
w.onmessage = onmessage; |
|
w.postMessage(buffer); |
|
}) |
|
}); |
|
} |
|
|
|
|
|
try { |
|
new SharedArrayBuffer(4); |
|
} |
|
catch (_) { |
|
SharedArrayBuffer = ArrayBuffer; |
|
|
|
const ids = new WeakMap; |
|
|
|
if (window) { |
|
const resolvers = new Map; |
|
const {prototype: {postMessage}} = Worker; |
|
|
|
const listener = event => { |
|
const details = event.data?.[CHANNEL]; |
|
if (!isArray(details)) { |
|
event.stopImmediatePropagation(); |
|
const { id, sb } = details; |
|
resolvers.get(id)(sb); |
|
} |
|
}; |
|
|
|
postPatched = function (data, ...rest) { |
|
const details = data?.[CHANNEL]; |
|
if (isArray(details)) { |
|
const [id, sb] = details; |
|
ids.set(sb, id); |
|
this.addEventListener('message', listener); |
|
} |
|
return postMessage.call(this, data, ...rest); |
|
}; |
|
|
|
waitAsync = sb => ({ |
|
value: new Promise(resolve => { |
|
resolvers.set(ids.get(sb), resolve); |
|
}).then(buff => { |
|
resolvers.delete(ids.get(sb)); |
|
ids.delete(sb); |
|
for (let i = 0; i < buff.length; i++) sb[i] = buff[i]; |
|
return 'ok'; |
|
}) |
|
}); |
|
} |
|
else { |
|
const as = (id, sb) => ({[CHANNEL]: { id, sb }}); |
|
|
|
notify = sb => { |
|
postMessage(as(ids.get(sb), sb)); |
|
}; |
|
|
|
addEventListener('message', event => { |
|
const details = event.data?.[CHANNEL]; |
|
if (isArray(details)) { |
|
const [id, sb] = details; |
|
ids.set(sb, id); |
|
} |
|
}); |
|
} |
|
} |
|
|
|
exports.SharedArrayBuffer = SharedArrayBuffer; |
|
exports.isArray = isArray; |
|
exports.notify = notify; |
|
exports.postPatched = postPatched; |
|
exports.wait = wait; |
|
exports.waitAsync = waitAsync; |
|
|