diff --git a/adapters/platforms/wechat/res/workers/handlers.js b/adapters/platforms/wechat/res/workers/handlers.js index 61bc407c..c00990f7 100644 --- a/adapters/platforms/wechat/res/workers/handlers.js +++ b/adapters/platforms/wechat/res/workers/handlers.js @@ -14,3 +14,8 @@ if (globalThis.CC_WORKER_HTTP_REQUEST) { const http = require("./http-worker.js"); registerHandler("http", http); } + +if (globalThis.CC_WORKER_WEBSOCKET) { + const ws = require("./ws-worker.js"); + registerHandler("ws", ws); +} diff --git a/adapters/platforms/wechat/res/workers/ws-worker.js b/adapters/platforms/wechat/res/workers/ws-worker.js new file mode 100644 index 00000000..378182c5 --- /dev/null +++ b/adapters/platforms/wechat/res/workers/ws-worker.js @@ -0,0 +1,58 @@ +const { main } = require("./ipc-worker.js"); + +var ws_worker = { + sockets: {}, + + connectSocket(id, url, protocols) { + try { + const ws = worker.connectSocket({ + url, + protocols, + tcpNoDelay: true, + }); + + this.sockets[id] = ws; + + ws.onOpen(() => { + main.wsAdapter.onOpen(id); + }); + + ws.onMessage(res => { + main.wsAdapter.onMessage(id, hookWSRecv ? hookWSRecv(res.data) : res.data); + }); + + ws.onError(res => { + delete this.sockets[id]; + main.wsAdapter.onError(id, res); + }); + + ws.onClose(res => { + delete this.sockets[id]; + main.wsAdapter.onClose(id, res); + }); + } catch (error) { + main.wsAdapter.onError(id, { errMsg: String(error) }); + } + }, + + send(id, data) { + const ws = this.sockets[id]; + if (ws) { + ws.send({ + data: hookWSSend ? hookWSSend(data) : data, + }); + } + }, + + close(id, code, reason) { + const ws = this.sockets[id]; + if (ws) { + ws.close({ + code, + reason, + }); + } + }, +}; + +module.exports = ws_worker; diff --git a/adapters/platforms/wechat/worker/handlers.js b/adapters/platforms/wechat/worker/handlers.js index e71d7aba..8f62eae9 100644 --- a/adapters/platforms/wechat/worker/handlers.js +++ b/adapters/platforms/wechat/worker/handlers.js @@ -9,3 +9,8 @@ if (CC_WORKER_AUDIO_SYSTEM) { ipcMain.registerHandler("audioAdapter", audioWorkerAdapter); } } + +if (CC_WORKER_WEBSOCKET) { + const wsWorkerAdapter = require("./ws.js"); + ipcMain.registerHandler("wsAdapter", wsWorkerAdapter); +} diff --git a/adapters/platforms/wechat/worker/ws.js b/adapters/platforms/wechat/worker/ws.js new file mode 100644 index 00000000..d56c6674 --- /dev/null +++ b/adapters/platforms/wechat/worker/ws.js @@ -0,0 +1,87 @@ +let _id = 0; + +class WorkerWebSocket { + id = _id++; + + onopen = null; + onclose = null; + onerror = null; + onmessage = null; + + constructor(url, protocols) { + wsWorkerAdapter.register(this); + worker.ws.connectSocket([this.id, url, protocols]); + } + + onOpen(cb) { + this.onopen = cb; + } + + onMessage(cb) { + this.onmessage = cb; + } + + onClose(cb) { + this.onclose = cb; + } + + onError(cb) { + this.onerror = cb; + } + + send(res) { + worker.ws.send([this.id, res.data]); + } + + close(res) { + worker.ws.close([this.id, res.code, res.reason]); + } +} + +var wsWorkerAdapter = { + sockets: {}, + + register(socket) { + this.sockets[socket.id] = socket; + }, + + onOpen(args, cmdId, callback) { + const id = args[0]; + const ws = this.sockets[id]; + if (ws) { + ws.onopen?.(); + } + }, + + onMessage(args, cmdId, callback) { + const id = args[0]; + const data = args[1]; + const ws = this.sockets[id]; + if (ws) { + ws.onmessage?.({ data }); + } + }, + + onClose(args, cmdId, callback) { + const id = args[0]; + const data = args[1]; + const ws = this.sockets[id]; + if (ws) { + ws.onclose?.(data); + delete this.sockets[id]; + } + }, + + onError(args, cmdId, callback) { + const id = args[0]; + const data = args[1]; + const ws = this.sockets[id]; + if (ws) { + ws.onerror?.(data); + delete this.sockets[id]; + } + }, +}; + +globalThis.WorkerWebSocket = WorkerWebSocket; +module.exports = wsWorkerAdapter; diff --git a/adapters/platforms/wechat/wrapper/builtin/WebSocket.js b/adapters/platforms/wechat/wrapper/builtin/WebSocket.js index afe2e087..e8629a60 100644 --- a/adapters/platforms/wechat/wrapper/builtin/WebSocket.js +++ b/adapters/platforms/wechat/wrapper/builtin/WebSocket.js @@ -26,11 +26,13 @@ export default class WebSocket { this.url = url this.readyState = WebSocket.CONNECTING - const socketTask = wx.connectSocket({ - url, - protocols: Array.isArray(protocols) ? protocols : [protocols], - tcpNoDelay: true - }) + const socketTask = CC_WORKER_WEBSOCKET + ? new WorkerWebSocket(url, Array.isArray(protocols) ? protocols : [protocols]) + : wx.connectSocket({ + url, + protocols: Array.isArray(protocols) ? protocols : [protocols], + tcpNoDelay: true + }); _socketTask.set(this, socketTask) @@ -74,8 +76,10 @@ export default class WebSocket { } send(data) { - if (typeof data !== 'string' && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) { - throw new TypeError(`Failed to send message: The data ${data} is invalid`) + if (!CC_WORKER_WEBSOCKET) { + if (typeof data !== 'string' && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) { + throw new TypeError(`Failed to send message: The data ${data} is invalid`) + } } const socketTask = _socketTask.get(this)