|
const messages = Symbol('messages'); |
|
const putters = Symbol('putters'); |
|
const takers = Symbol('takers'); |
|
const racers = Symbol('racers'); |
|
/* private methods */ |
|
function race(ch) { |
|
return new Promise(resolve => { |
|
ch[racers].unshift(resolve); |
|
if (ch[putters].length) |
|
ch[racers].pop()(ch); |
|
}); |
|
} |
|
function map(sel, fn) { |
|
if (sel instanceof Set) { |
|
return [...sel.values()].map(ch => fn(ch, ch)); |
|
} |
|
else if (sel instanceof Map) { |
|
return [...sel.entries()].map(([k, v]) => fn(v, k)); |
|
} |
|
else if (Array.isArray(sel)) { |
|
return sel.map(fn); |
|
} |
|
return Object.entries(sel).map(([k, v]) => fn(v, k)); |
|
} |
|
function forEach(sel, fn) { |
|
if (sel instanceof Set) { |
|
return sel.forEach(fn); |
|
} |
|
else if (sel instanceof Map) { |
|
return sel.forEach(fn); |
|
} |
|
else if (Array.isArray(sel)) { |
|
return sel.forEach(fn); |
|
} |
|
return Object.values(sel).forEach(fn); |
|
} |
|
/* public methods */ |
|
function channel() { |
|
return { |
|
[messages]: [], |
|
[putters]: [], |
|
[takers]: [], |
|
[racers]: [], |
|
async *[Symbol.asyncIterator]() { |
|
while (true) { |
|
yield await _take(this); |
|
} |
|
} |
|
}; |
|
} |
|
function put(ch, msg) { |
|
return new Promise(resolve => { |
|
ch[messages].unshift(msg); |
|
ch[putters].unshift(resolve); |
|
if (ch[takers].length) { |
|
ch[putters].pop()(); |
|
ch[takers].pop()(ch[messages].pop()); |
|
} |
|
if (ch[racers].length) |
|
ch[racers].pop()(ch); |
|
}); |
|
} |
|
function _take(ch) { |
|
return new Promise(resolve => { |
|
ch[takers].unshift(resolve); |
|
if (ch[putters].length) { |
|
ch[putters].pop()(); |
|
ch[takers].pop()(ch[messages].pop()); |
|
} |
|
}); |
|
} |
|
function take(ch) { |
|
const promise = _take(ch); |
|
return Object.assign(promise, { |
|
async *[Symbol.asyncIterator]() { |
|
yield await promise; |
|
while (true) { |
|
yield await _take(ch); |
|
} |
|
} |
|
}); |
|
} |
|
function _alts(...chs) { |
|
return Promise |
|
.race(chs.map(ch => race(ch))) |
|
.then(ch => { |
|
chs.forEach(c => c !== ch && c[racers].pop()); |
|
ch[putters].pop()(); |
|
return ch[messages].pop(); |
|
}); |
|
} |
|
function alts(...chs) { |
|
const promise = _alts(...chs); |
|
return Object.assign(promise, { |
|
async *[Symbol.asyncIterator]() { |
|
yield await promise; |
|
while (true) { |
|
yield await _alts(...chs); |
|
} |
|
} |
|
}); |
|
} |
|
function _select(chs) { |
|
return Promise |
|
.race(map(chs, (ch, key) => race(ch).then(result => [key, result]))) |
|
.then(([key, ch]) => { |
|
forEach(chs, c => c !== ch && c[racers].pop()); |
|
ch[putters].pop()(); |
|
return [key, ch[messages].pop()]; |
|
}); |
|
} |
|
function select(chs) { |
|
const promise = _select(chs); |
|
return Object.assign(promise, { |
|
async *[Symbol.asyncIterator]() { |
|
yield await promise; |
|
while (true) { |
|
yield await _select(chs); |
|
} |
|
} |
|
}); |
|
} |
|
function drain(ch) { |
|
const msgs = []; |
|
while (ch[messages].length) |
|
msgs.push(take(ch)); |
|
return Promise.all(msgs); |
|
} |
|
export { channel, put, take, alts, select, drain }; |
@f5io I found this Gist whilst googling
"error: redefinition of 'qjsc_index_size'"
. My issue turned out to be an outdated version of these files:I naïvely built QuickJS using
make
instead ofmake install
, and manually symlinked the resultingqjsc
binary. When I ranmake install
, the error disappeared and the executable ran perfectly fine.Hope that helps. 👍