UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

122 lines (118 loc) 4.31 kB
'use strict'; var chan = require('../chan.js'); var env = require('../env.js'); const channelStore = new Map(); function isChannelMessage(msg) { return msg && typeof msg === "object" && ["send", "close"].includes(msg.type) && typeof msg.channelId === "number"; } async function handleChannelMessage(msg) { const record = channelStore.get(msg.channelId); if (!record) return; if (msg.type === "send") { await record.raw.send(msg.value); } else if (msg.type === "close") { const { value: err, channelId } = msg; record.raw.close(err); channelStore.delete(channelId); if (env.isMainThread && record.writers.length > 1) { // distribute the channel close event to all threads record.writers.forEach(write => { write("close", err, channelId); }); } } } function wireChannel(channel, channelWrite) { const channelId = channel[env.id]; if (!channelStore.has(channelId)) { const send = channel.send.bind(channel); const close = channel.close.bind(channel); channelStore.set(channelId, { channel, raw: { send, close }, writers: [channelWrite], counter: 0, }); Object.defineProperties(channel, { send: { configurable: true, writable: true, value: async (data) => { const record = channelStore.get(channelId); if (record) { const channel = record.channel; if (channel["state"] !== 1) { throw new Error("the channel is closed"); } const write = record.writers[record.counter++ % record.writers.length]; await Promise.resolve(write("send", data, channelId)); } }, }, close: { configurable: true, writable: true, value: (err = null) => { const record = channelStore.get(channelId); if (record) { channelStore.delete(channelId); const channel = record.channel; record.writers.forEach(write => { write("close", err, channelId); }); // recover to the original methods Object.defineProperties(channel, { send: { configurable: true, writable: true, value: record.raw.send, }, close: { configurable: true, writable: true, value: record.raw.close, }, }); channel.close(err); } }, }, }); } else { const record = channelStore.get(channelId); record.writers.push(channelWrite); } } function wrapChannel(channel, channelWrite) { wireChannel(channel, channelWrite); return { "@@type": "Channel", "@@id": channel[env.id], "capacity": channel.capacity }; } function unwrapChannel(obj, channelWrite) { var _a, _b; const channelId = obj["@@id"]; let channel = (_a = channelStore.get(channelId)) === null || _a === void 0 ? void 0 : _a.channel; if (!channel) { channel = Object.assign(Object.create(chan.Channel.prototype), { [env.id]: channelId, capacity: (_b = obj.capacity) !== null && _b !== void 0 ? _b : 0, buffer: [], producers: [], consumers: [], error: null, state: 1, }); } wireChannel(channel, channelWrite); return channel; } exports.handleChannelMessage = handleChannelMessage; exports.isChannelMessage = isChannelMessage; exports.unwrapChannel = unwrapChannel; exports.wrapChannel = wrapChannel; //# sourceMappingURL=channel.js.map